diff --git a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml index 1cb6bb99d61c8..17ab552f3c65d 100755 --- a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml +++ b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml @@ -346,6 +346,10 @@ + + - + @@ -2414,4 +2414,13 @@ + + + + + + + + + diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes128CbcPad.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes128CbcPad.java new file mode 100644 index 0000000000000..c8522e89170a6 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes128CbcPad.java @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.cryptography; + +class Aes128CbcPad extends AesCbcPad { + private static final int KEY_SIZE = 128; + public static final String ALGORITHM_NAME = "A128CBCPAD"; + + Aes128CbcPad() { + super(ALGORITHM_NAME, KEY_SIZE); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes128Gcm.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes128Gcm.java new file mode 100644 index 0000000000000..12fa7834e6ea3 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes128Gcm.java @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.cryptography; + +class Aes128Gcm extends AesGcm { + private static final int KEY_SIZE = 128; + public static final String ALGORITHM_NAME = "A128GCM"; + + Aes128Gcm() { + super(ALGORITHM_NAME, KEY_SIZE); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw128.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes128Kw.java similarity index 96% rename from sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw128.java rename to sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes128Kw.java index 62043a73194ce..7da65997b4613 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw128.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes128Kw.java @@ -10,13 +10,13 @@ import java.security.Provider; import java.util.Arrays; -class AesKw128 extends AesKw { +class Aes128Kw extends AesKw { public static final String ALGORITHM_NAME = "A128KW"; static final int KEY_SIZE_IN_BYTES = 128 >> 3; - AesKw128() { + Aes128Kw() { super(ALGORITHM_NAME); } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes192CbcPad.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes192CbcPad.java new file mode 100644 index 0000000000000..a68ae47f5713f --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes192CbcPad.java @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.cryptography; + +class Aes192CbcPad extends AesCbcPad { + private static final int KEY_SIZE = 192; + public static final String ALGORITHM_NAME = "A192CBCPAD"; + + Aes192CbcPad() { + super(ALGORITHM_NAME, KEY_SIZE); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes192Gcm.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes192Gcm.java new file mode 100644 index 0000000000000..6ea8049a0f41b --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes192Gcm.java @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.cryptography; + +class Aes192Gcm extends AesGcm { + private static final int KEY_SIZE = 192; + public static final String ALGORITHM_NAME = "A192GCM"; + + Aes192Gcm() { + super(ALGORITHM_NAME, KEY_SIZE); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw192.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes192Kw.java similarity index 96% rename from sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw192.java rename to sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes192Kw.java index 0af9bd7207dd8..cfe8388a14328 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw192.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes192Kw.java @@ -10,13 +10,13 @@ import java.security.Provider; import java.util.Arrays; -class AesKw192 extends AesKw { +class Aes192Kw extends AesKw { public static final String ALGORITHM_NAME = "A192KW"; static final int KEY_SIZE_IN_BYTES = 192 >> 3; - AesKw192() { + Aes192Kw() { super(ALGORITHM_NAME); } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes256CbcPad.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes256CbcPad.java new file mode 100644 index 0000000000000..ac8c4478161d2 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes256CbcPad.java @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.cryptography; + +class Aes256CbcPad extends AesCbcPad { + private static final int KEY_SIZE = 256; + public static final String ALGORITHM_NAME = "A256CBCPAD"; + + Aes256CbcPad() { + super(ALGORITHM_NAME, KEY_SIZE); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes256Gcm.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes256Gcm.java new file mode 100644 index 0000000000000..39ff27b5d40d6 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes256Gcm.java @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.cryptography; + +class Aes256Gcm extends AesGcm { + private static final int KEY_SIZE = 256; + public static final String ALGORITHM_NAME = "A256GCM"; + + Aes256Gcm() { + super(ALGORITHM_NAME, KEY_SIZE); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw256.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes256Kw.java similarity index 96% rename from sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw256.java rename to sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes256Kw.java index 3448b82490f42..d26a198be251c 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw256.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/Aes256Kw.java @@ -10,13 +10,13 @@ import java.security.Provider; import java.util.Arrays; -class AesKw256 extends AesKw { +class Aes256Kw extends AesKw { public static final String ALGORITHM_NAME = "A256KW"; static final int KEY_SIZE_IN_BYTES = 256 >> 3; - AesKw256() { + Aes256Kw() { super(ALGORITHM_NAME); } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbc.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbc.java index dc3816dbe4df5..d72fdf079b7a5 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbc.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbc.java @@ -16,25 +16,30 @@ import java.util.Arrays; abstract class AesCbc extends SymmetricEncryptionAlgorithm { - final int keySizeInBytes; final int keySize; - static class AesCbcDecryptor implements ICryptoTransform { + protected AesCbc(String name, int size) { + super(name); + + keySize = size; + keySizeInBytes = size >> 3; + } + + static class AesCbcEncryptor implements ICryptoTransform { private final Cipher cipher; - AesCbcDecryptor(byte[] key, byte[] iv, Provider provider) - throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, - InvalidAlgorithmParameterException { + AesCbcEncryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Create the cipher using the Provider if specified if (provider == null) { - cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher = Cipher.getInstance("AES/CBC/NoPadding"); } else { - cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", provider); + cipher = Cipher.getInstance("AES/CBC/NoPadding", provider); } - cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv)); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv)); } @Override @@ -43,22 +48,20 @@ public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPad } } - static class AesCbcEncryptor implements ICryptoTransform { - + static class AesCbcDecryptor implements ICryptoTransform { private final Cipher cipher; - AesCbcEncryptor(byte[] key, byte[] iv, Provider provider) - throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, - InvalidAlgorithmParameterException { + AesCbcDecryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { // Create the cipher using the Provider if specified if (provider == null) { - cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher = Cipher.getInstance("AES/CBC/NoPadding"); } else { - cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", provider); + cipher = Cipher.getInstance("AES/CBC/NoPadding", provider); } - cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv)); + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv)); } @Override @@ -67,56 +70,45 @@ public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPad } } - protected AesCbc(String name, int size) { - super(name); - keySize = size; - keySizeInBytes = size >> 3; - } - @Override - public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] authenticationData) + public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException { - if (key == null || key.length < keySizeInBytes) { - throw new InvalidKeyException("key must be at least " + keySize + " bits in length"); - } - - return new AesCbcEncryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, null); + return createEncryptor(key, iv, additionalAuthenticatedData, null, null); } @Override - public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] authenticationData, Provider provider) + public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException { if (key == null || key.length < keySizeInBytes) { - throw new InvalidKeyException("key must be at least " + keySize + " bits in length"); + throw new InvalidKeyException("Key must be at least " + keySize + " bits in length."); } return new AesCbcEncryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, provider); } @Override - public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag) + public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException { - if (key == null || key.length < keySizeInBytes) { - throw new InvalidKeyException("key must be at least " + keySize + " bits in length"); - } - - return new AesCbcDecryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, null); + return createDecryptor(key, iv, additionalAuthenticatedData, authenticationTag, null); } @Override - public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag, - Provider provider) + public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException { if (key == null || key.length < keySizeInBytes) { - throw new InvalidKeyException("key must be at least " + keySize + " bits in length"); + throw new InvalidKeyException("Key must be at least " + keySize + " bits in length."); } return new AesCbcDecryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, provider); diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbcHmacSha2.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbcHmacSha2.java index 91f9d3e3f53be..96cbdb913d99e 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbcHmacSha2.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbcHmacSha2.java @@ -188,15 +188,17 @@ protected AesCbcHmacSha2(String name) { } @Override - public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag) + public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException { - return createDecryptor(key, iv, authenticationData, authenticationTag, null); + + return createDecryptor(key, iv, additionalAuthenticatedData, authenticationTag, null); } @Override - public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] authenticationData, byte[] authenticationTag, - Provider provider) + public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException { if (key == null) { @@ -207,7 +209,7 @@ public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] authentica throw logger.logExceptionAsWarning(new IllegalArgumentException("No initialization vector")); } - if (authenticationData == null) { + if (additionalAuthenticatedData == null) { throw logger.logExceptionAsWarning(new IllegalArgumentException("No authentication data")); } @@ -216,18 +218,21 @@ public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] authentica } // Create the Decryptor - return new AesCbcHmacSha2Decryptor(getName(), key, iv, authenticationData, authenticationTag, provider); + return new AesCbcHmacSha2Decryptor(getName(), key, iv, additionalAuthenticatedData, authenticationTag, provider); } @Override - public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] authenticationData) + public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException { - return createEncryptor(key, iv, authenticationData, null); + + return createEncryptor(key, iv, additionalAuthenticatedData, null, null); } @Override - public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] authenticationData, Provider provider) + public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException { @@ -239,11 +244,11 @@ public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] authentica throw logger.logExceptionAsError(new IllegalArgumentException("No initialization vector")); } - if (authenticationData == null) { + if (additionalAuthenticatedData == null) { throw logger.logExceptionAsError(new IllegalArgumentException("No authentication data")); } // Create the Encryptor - return new AesCbcHmacSha2Encryptor(getName(), key, iv, authenticationData, provider); + return new AesCbcHmacSha2Encryptor(getName(), key, iv, additionalAuthenticatedData, provider); } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbcPad.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbcPad.java new file mode 100644 index 0000000000000..114f4f90e32a7 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesCbcPad.java @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.cryptography; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.util.Arrays; + +abstract class AesCbcPad extends SymmetricEncryptionAlgorithm { + final int keySizeInBytes; + final int keySize; + + protected AesCbcPad(String name, int size) { + super(name); + + keySize = size; + keySizeInBytes = size >> 3; + } + + static class AesCbcPadEncryptor implements ICryptoTransform { + private final Cipher cipher; + + AesCbcPadEncryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { + + // Create the cipher using the Provider if specified + if (provider == null) { + cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + } else { + cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", provider); + } + + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv)); + } + + @Override + public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException { + return cipher.doFinal(plaintext); + } + } + + static class AesCbcPadDecryptor implements ICryptoTransform { + private final Cipher cipher; + + AesCbcPadDecryptor(byte[] key, byte[] iv, Provider provider) throws NoSuchAlgorithmException, + NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException { + + // Create the cipher using the Provider if specified + if (provider == null) { + cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + } else { + cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", provider); + } + + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv)); + } + + @Override + public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException { + return cipher.doFinal(plaintext); + } + } + + @Override + public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag) + throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, + InvalidAlgorithmParameterException { + + return createEncryptor(key, iv, additionalAuthenticatedData, null, null); + } + + @Override + public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag, Provider provider) + throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, + InvalidAlgorithmParameterException { + + if (key == null || key.length < keySizeInBytes) { + throw new InvalidKeyException("key must be at least " + keySize + " bits in length"); + } + + return new AesCbcPadEncryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, provider); + } + + @Override + public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag) + throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, + InvalidAlgorithmParameterException { + + return createDecryptor(key, iv, additionalAuthenticatedData, authenticationTag, null); + } + + @Override + public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag, Provider provider) + throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, + InvalidAlgorithmParameterException { + + if (key == null || key.length < keySizeInBytes) { + throw new InvalidKeyException("key must be at least " + keySize + " bits in length"); + } + + return new AesCbcPadDecryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, provider); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesGcm.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesGcm.java new file mode 100644 index 0000000000000..d0a6ddd5e1465 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesGcm.java @@ -0,0 +1,128 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.cryptography; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.util.Arrays; +import java.util.Objects; + +abstract class AesGcm extends SymmetricEncryptionAlgorithm { + final int keySizeInBytes; + final int keySize; + + protected AesGcm(String name, int size) { + super(name); + + keySize = size; + keySizeInBytes = size >> 3; + } + + static class AesGcmEncryptor implements ICryptoTransform { + private final Cipher cipher; + + AesGcmEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, byte[] authenticationTag, + Provider provider) + throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, + InvalidAlgorithmParameterException { + + // Create the cipher using the Provider if specified + if (provider == null) { + cipher = Cipher.getInstance("AES/GCM/NoPadding"); + } else { + cipher = Cipher.getInstance("AES/GCM/NoPadding", provider); + } + + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), + new GCMParameterSpec(authenticationTag.length << 3, iv)); + } + + @Override + public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException { + return cipher.doFinal(plaintext); + } + } + + static class AesGcmDecryptor implements ICryptoTransform { + private final Cipher cipher; + + AesGcmDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, byte[] authenticationTag, + Provider provider) + throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, + InvalidAlgorithmParameterException { + + // Create the cipher using the Provider if specified + if (provider == null) { + cipher = Cipher.getInstance("AES/GCM/NoPadding"); + } else { + cipher = Cipher.getInstance("AES/GCM/NoPadding", provider); + } + + + Objects.requireNonNull(authenticationTag, "'authenticationTag' cannot be null"); + + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), + new GCMParameterSpec(authenticationTag.length << 3, iv)); + } + + @Override + public byte[] doFinal(byte[] plaintext) throws IllegalBlockSizeException, BadPaddingException { + return cipher.doFinal(plaintext); + } + } + + @Override + public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag) + throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, + InvalidAlgorithmParameterException { + + return createEncryptor(key, iv, additionalAuthenticatedData, authenticationTag, null); + } + + @Override + public ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag, Provider provider) + throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, + InvalidAlgorithmParameterException { + + if (key == null || key.length < keySizeInBytes) { + throw new InvalidKeyException("key must be at least " + keySize + " bits in length"); + } + + return new AesGcmEncryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, additionalAuthenticatedData, + authenticationTag, provider); + } + + @Override + public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag) + throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, + InvalidAlgorithmParameterException { + + return createDecryptor(key, iv, additionalAuthenticatedData, authenticationTag, null); + } + + @Override + public ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag, Provider provider) + throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, + InvalidAlgorithmParameterException { + + if (key == null || key.length < keySizeInBytes) { + throw new InvalidKeyException("key must be at least " + keySize + " bits in length"); + } + + return new AesGcmDecryptor(Arrays.copyOfRange(key, 0, keySizeInBytes), iv, additionalAuthenticatedData, + authenticationTag, provider); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw.java index 66f6ccc0a90c9..e7fe66a1be746 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AesKw.java @@ -17,6 +17,7 @@ import java.security.Provider; abstract class AesKw extends LocalKeyWrapAlgorithm { + static final int BLOCK_SIZE_IN_BITS = 64; static final byte[] DEFAULT_IV = new byte[]{(byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6}; @@ -133,8 +134,9 @@ public ICryptoTransform createEncryptor(byte[] key, byte[] iv, Provider provider if (iv != null) { // iv length must be 64 bits - if (iv.length != 8) { - throw logger.logExceptionAsError(new IllegalArgumentException("iv length must be 64 bits")); + if (iv.length != BLOCK_SIZE_IN_BITS >> 3) { + throw logger.logExceptionAsError(new IllegalArgumentException(String.format( + "iv length must be %s bits", BLOCK_SIZE_IN_BITS))); } // iv cannot be specified with the default provider if (provider == null) { @@ -186,8 +188,9 @@ public ICryptoTransform createDecryptor(byte[] key, byte[] iv, Provider provider if (iv != null) { // iv length must be 64 bits - if (iv.length != 8) { - throw logger.logExceptionAsError(new IllegalArgumentException("iv length must be 64 bits")); + if (iv.length != BLOCK_SIZE_IN_BITS >> 3) { + throw logger.logExceptionAsError(new IllegalArgumentException(String.format( + "iv length must be %s bits", BLOCK_SIZE_IN_BITS))); } // iv cannot be specified with the default provider if (provider == null) { diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AlgorithmResolver.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AlgorithmResolver.java index ad703e5c170a9..8d9bcb1263dbf 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AlgorithmResolver.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/AlgorithmResolver.java @@ -11,17 +11,25 @@ class AlgorithmResolver { public static final AlgorithmResolver Default = new AlgorithmResolver(); static { + Default.put(Aes128Cbc.ALGORITHM_NAME, new Aes128Cbc()); + Default.put(Aes192Cbc.ALGORITHM_NAME, new Aes192Cbc()); + Default.put(Aes256Cbc.ALGORITHM_NAME, new Aes256Cbc()); + + Default.put(Aes128CbcPad.ALGORITHM_NAME, new Aes128CbcPad()); + Default.put(Aes192CbcPad.ALGORITHM_NAME, new Aes192CbcPad()); + Default.put(Aes256CbcPad.ALGORITHM_NAME, new Aes256CbcPad()); + Default.put(Aes128CbcHmacSha256.ALGORITHM_NAME, new Aes128CbcHmacSha256()); Default.put(Aes192CbcHmacSha384.ALGORITHM_NAME, new Aes192CbcHmacSha384()); Default.put(Aes256CbcHmacSha512.ALGORITHM_NAME, new Aes256CbcHmacSha512()); - Default.put(Aes128Cbc.ALGORITHM_NAME, new Aes128Cbc()); - Default.put(Aes192Cbc.ALGORITHM_NAME, new Aes192Cbc()); - Default.put(Aes256Cbc.ALGORITHM_NAME, new Aes256Cbc()); + Default.put(Aes128Gcm.ALGORITHM_NAME, new Aes128Gcm()); + Default.put(Aes192Gcm.ALGORITHM_NAME, new Aes192Gcm()); + Default.put(Aes256Gcm.ALGORITHM_NAME, new Aes256Gcm()); - Default.put(AesKw128.ALGORITHM_NAME, new AesKw128()); - Default.put(AesKw192.ALGORITHM_NAME, new AesKw192()); - Default.put(AesKw256.ALGORITHM_NAME, new AesKw256()); + Default.put(Aes128Kw.ALGORITHM_NAME, new Aes128Kw()); + Default.put(Aes192Kw.ALGORITHM_NAME, new Aes192Kw()); + Default.put(Aes256Kw.ALGORITHM_NAME, new Aes256Kw()); Default.put(Rsa15.ALGORITHM_NAME, new Rsa15()); Default.put(RsaOaep.ALGORITHM_NAME, new RsaOaep()); diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyAsyncClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyAsyncClient.java index e758d5fff1217..2c2b999c9c0fd 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyAsyncClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyAsyncClient.java @@ -196,14 +196,17 @@ Mono getSecretKey() { * portion of the key is used for encryption. This operation requires the keys/encrypt permission. * *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for encrypting the - * specified {@code plaintext}. Possible values for assymetric keys include: + * specified {@code plaintext}. Possible values for asymmetric keys include: * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. * * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, - * {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, {@link EncryptionAlgorithm#A192CBC A192CBC}, - * {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, {@link EncryptionAlgorithm#A256CBC A256CBC} and - * {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512}

+ * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

* *

Code Samples

*

Encrypts the content. Subscribes to the call asynchronously and prints out the encrypted content details when @@ -213,35 +216,71 @@ Mono getSecretKey() { * @param algorithm The algorithm to be used for encryption. * @param plaintext The content to be encrypted. * @return A {@link Mono} containing a {@link EncryptResult} whose {@link EncryptResult#getCipherText() cipher text} - * contains the encrypted content. - * @throws ResourceNotFoundException if the key cannot be found for encryption. - * @throws UnsupportedOperationException if the encrypt operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code plainText} is null. + * contains the encrypted content. + * @throws ResourceNotFoundException If the key cannot be found for encryption. + * @throws UnsupportedOperationException If the encrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code plaintext} are {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono encrypt(EncryptionAlgorithm algorithm, byte[] plaintext) { + return encrypt(new EncryptOptions(algorithm, plaintext, null, null), null); + } + + /** + * Encrypts an arbitrary sequence of bytes using the configured key. Note that the encrypt operation only supports a + * single block of data, the size of which is dependent on the target key and the encryption algorithm to be used. + * The encrypt operation is supported for both symmetric keys and asymmetric keys. In case of asymmetric keys public + * portion of the key is used for encryption. This operation requires the keys/encrypt permission. + * + *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for encrypting the + * specified {@code plaintext}. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

+ * + *

Code Samples

+ *

Encrypts the content. Subscribes to the call asynchronously and prints out the encrypted content details when + * a response has been received.

+ * {@codesnippet com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.encrypt#EncryptOptions} + * + * @param encryptOptions The parameters to use in the encryption operation. + * @return A {@link Mono} containing a {@link EncryptResult} whose {@link EncryptResult#getCipherText() cipher text} + * contains the encrypted content. + * @throws ResourceNotFoundException If the key cannot be found for encryption. + * @throws UnsupportedOperationException If the encrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code encryptOptions} is {@code null}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono encrypt(EncryptOptions encryptOptions) { + Objects.requireNonNull(encryptOptions, "'encryptOptions' cannot be null"); + try { - return withContext(context -> encrypt(algorithm, plaintext, context)); + return withContext(context -> encrypt(encryptOptions, context)); } catch (RuntimeException ex) { return monoError(logger, ex); } } - Mono encrypt(EncryptionAlgorithm algorithm, byte[] plaintext, Context context) { - Objects.requireNonNull(algorithm, "Encryption algorithm cannot be null."); - Objects.requireNonNull(plaintext, "Plain text content to be encrypted cannot be null."); - + Mono encrypt(EncryptOptions encryptOptions, Context context) { return ensureValidKeyAvailable().flatMap(available -> { if (!available) { - return cryptographyServiceClient.encrypt(algorithm, plaintext, context); + return cryptographyServiceClient.encrypt(encryptOptions, context); } if (!checkKeyPermissions(this.key.getKeyOps(), KeyOperation.ENCRYPT)) { - return Mono.error(logger.logExceptionAsError(new UnsupportedOperationException(String.format("Encrypt Operation is missing " - + "permission/not supported for key with id %s", key.getId())))); + return Mono.error(logger.logExceptionAsError(new UnsupportedOperationException(String.format( + "Encrypt Operation is missing permission/not supported for key with id %s", key.getId())))); } - return localKeyCryptographyClient.encryptAsync(algorithm, plaintext, context, key); + + return localKeyCryptographyClient.encryptAsync(encryptOptions, context, key); }); } @@ -252,14 +291,17 @@ Mono encrypt(EncryptionAlgorithm algorithm, byte[] plaintext, Con * keys/decrypt permission. * *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the - * specified encrypted content. Possible values for assymetric keys include: + * specified encrypted content. Possible values for asymmetric keys include: * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and {@link * EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. * * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, - * {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, {@link EncryptionAlgorithm#A192CBC A192CBC}, - * {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, {@link - * EncryptionAlgorithm#A256CBC A256CBC} and {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512}

+ * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

* *

Code Samples

*

Decrypts the encrypted content. Subscribes to the call asynchronously and prints out the decrypted content @@ -267,34 +309,70 @@ Mono encrypt(EncryptionAlgorithm algorithm, byte[] plaintext, Con * {@codesnippet com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.decrypt#EncryptionAlgorithm-byte} * * @param algorithm The algorithm to be used for decryption. - * @param cipherText The content to be decrypted. + * @param ciphertext The content to be decrypted. * @return A {@link Mono} containing the decrypted blob. - * @throws ResourceNotFoundException if the key cannot be found for decryption. - * @throws UnsupportedOperationException if the decrypt operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code cipherText} is null. + * @throws ResourceNotFoundException If the key cannot be found for decryption. + * @throws UnsupportedOperationException If the decrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code ciphertext} are {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) - public Mono decrypt(EncryptionAlgorithm algorithm, byte[] cipherText) { + public Mono decrypt(EncryptionAlgorithm algorithm, byte[] ciphertext) { + return decrypt(new DecryptOptions(algorithm, ciphertext, null, null, null)); + } + + /** + * Decrypts a single block of encrypted data using the configured key and specified algorithm. Note that only a + * single block of data may be decrypted, the size of this block is dependent on the target key and the algorithm to + * be used. The decrypt operation is supported for both asymmetric and symmetric keys. This operation requires the + * keys/decrypt permission. + * + *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the + * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and {@link + * EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

+ * + *

Code Samples

+ *

Decrypts the encrypted content. Subscribes to the call asynchronously and prints out the decrypted content + * details when a response has been received.

+ * {@codesnippet com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.decrypt#DecryptOptions} + * + * @param decryptOptions The parameters to use in the decryption operation. + * @return A {@link Mono} containing the decrypted blob. + * @throws ResourceNotFoundException If the key cannot be found for decryption. + * @throws UnsupportedOperationException If the decrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code decryptOptions} is {@code null}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono decrypt(DecryptOptions decryptOptions) { + Objects.requireNonNull(decryptOptions, "'decryptOptions' cannot be null"); + try { - return withContext(context -> decrypt(algorithm, cipherText, context)); + return withContext(context -> decrypt(decryptOptions, context)); } catch (RuntimeException ex) { return monoError(logger, ex); } } - Mono decrypt(EncryptionAlgorithm algorithm, byte[] cipherText, Context context) { - Objects.requireNonNull(algorithm, "Encryption algorithm cannot be null."); - Objects.requireNonNull(cipherText, "Cipher text content to be decrypted cannot be null."); + Mono decrypt(DecryptOptions decryptOptions, Context context) { return ensureValidKeyAvailable().flatMap(available -> { if (!available) { - return cryptographyServiceClient.decrypt(algorithm, cipherText, context); + return cryptographyServiceClient.decrypt(decryptOptions, context); } if (!checkKeyPermissions(this.key.getKeyOps(), KeyOperation.DECRYPT)) { - return Mono.error(logger.logExceptionAsError(new UnsupportedOperationException(String.format("Decrypt Operation is not allowed for " - + "key with id %s", key.getId())))); + return Mono.error(logger.logExceptionAsError(new UnsupportedOperationException(String.format( + "Decrypt Operation is not allowed for key with id %s", key.getId())))); } - return localKeyCryptographyClient.decryptAsync(algorithm, cipherText, context, key); + + return localKeyCryptographyClient.decryptAsync(decryptOptions, context, key); }); } @@ -407,7 +485,10 @@ Mono verify(SignatureAlgorithm algorithm, byte[] digest, byte[] si *

The {@link KeyWrapAlgorithm wrap algorithm} indicates the type of algorithm to use for wrapping the specified * key content. Possible values include: * {@link KeyWrapAlgorithm#RSA1_5 RSA1_5}, {@link KeyWrapAlgorithm#RSA_OAEP RSA_OAEP} and {@link - * KeyWrapAlgorithm#RSA_OAEP_256 RSA_OAEP_256}

+ * KeyWrapAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128KW A128KW}, + * {@link EncryptionAlgorithm#A192KW A192KW} and {@link EncryptionAlgorithm#A256KW A256KW}.

* *

Code Samples

*

Wraps the key content. Subscribes to the call asynchronously and prints out the wrapped key details when a @@ -415,12 +496,12 @@ Mono verify(SignatureAlgorithm algorithm, byte[] digest, byte[] si * {@codesnippet com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.wrapKey#KeyWrapAlgorithm-byte} * * @param algorithm The encryption algorithm to use for wrapping the key. - * @param key The key content to be wrapped - * @return A {@link Mono} containing a {@link WrapResult} whose {@link WrapResult#getEncryptedKey() encrypted - * key} contains the wrapped key result. - * @throws ResourceNotFoundException if the key cannot be found for wrap operation. - * @throws UnsupportedOperationException if the wrap operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code key} is null. + * @param key The key content to be wrapped. + * @return A {@link Mono} containing a {@link WrapResult} whose {@link WrapResult#getEncryptedKey() encrypted key} + * contains the wrapped key result. + * @throws ResourceNotFoundException If the key cannot be found for wrap operation. + * @throws UnsupportedOperationException If the wrap operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code key} are {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono wrapKey(KeyWrapAlgorithm algorithm, byte[] key) { @@ -434,14 +515,15 @@ public Mono wrapKey(KeyWrapAlgorithm algorithm, byte[] key) { Mono wrapKey(KeyWrapAlgorithm algorithm, byte[] key, Context context) { Objects.requireNonNull(algorithm, "Key Wrap algorithm cannot be null."); Objects.requireNonNull(key, "Key content to be wrapped cannot be null."); + return ensureValidKeyAvailable().flatMap(available -> { if (!available) { return cryptographyServiceClient.wrapKey(algorithm, key, context); } if (!checkKeyPermissions(this.key.getKeyOps(), KeyOperation.WRAP_KEY)) { - return Mono.error(logger.logExceptionAsError(new UnsupportedOperationException(String.format("Wrap Key Operation is not allowed for " - + "key with id %s", this.key.getId())))); + return Mono.error(logger.logExceptionAsError(new UnsupportedOperationException(String.format( + "Wrap Key Operation is not allowed for key with id %s", this.key.getId())))); } return localKeyCryptographyClient.wrapKeyAsync(algorithm, key, context, this.key); @@ -450,16 +532,16 @@ Mono wrapKey(KeyWrapAlgorithm algorithm, byte[] key, Context context /** * Unwraps a symmetric key using the configured key that was initially used for wrapping that key. This operation is - * the reverse of the wrap operation. - * The unwrap operation supports asymmetric and symmetric keys to unwrap. This operation requires the keys/unwrapKey - * permission. + * the reverse of the wrap operation. The unwrap operation supports asymmetric and symmetric keys to unwrap. This + * operation requires the keys/unwrapKey permission. * *

The {@link KeyWrapAlgorithm wrap algorithm} indicates the type of algorithm to use for unwrapping the * specified encrypted key content. Possible values for asymmetric keys include: * {@link KeyWrapAlgorithm#RSA1_5 RSA1_5}, {@link KeyWrapAlgorithm#RSA_OAEP RSA_OAEP} and {@link * KeyWrapAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. - * Possible values for symmetric keys include: {@link KeyWrapAlgorithm#A128KW A128KW}, {@link - * KeyWrapAlgorithm#A192KW A192KW} and {@link KeyWrapAlgorithm#A256KW A256KW}

+ * + * Possible values for symmetric keys include: {@link KeyWrapAlgorithm#A128KW A128KW}, + * {@link KeyWrapAlgorithm#A192KW A192KW} and {@link KeyWrapAlgorithm#A256KW A256KW}.

* *

Code Samples

*

Unwraps the key content. Subscribes to the call asynchronously and prints out the unwrapped key details when a @@ -469,9 +551,9 @@ Mono wrapKey(KeyWrapAlgorithm algorithm, byte[] key, Context context * @param algorithm The encryption algorithm to use for wrapping the key. * @param encryptedKey The encrypted key content to unwrap. * @return A {@link Mono} containing a the unwrapped key content. - * @throws ResourceNotFoundException if the key cannot be found for wrap operation. - * @throws UnsupportedOperationException if the unwrap operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code encryptedKey} is null. + * @throws ResourceNotFoundException If the key cannot be found for wrap operation. + * @throws UnsupportedOperationException If the unwrap operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code encryptedKey} are {@code null}. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono unwrapKey(KeyWrapAlgorithm algorithm, byte[] encryptedKey) { @@ -492,9 +574,10 @@ Mono unwrapKey(KeyWrapAlgorithm algorithm, byte[] encryptedKey, Co } if (!checkKeyPermissions(this.key.getKeyOps(), KeyOperation.UNWRAP_KEY)) { - return Mono.error(logger.logExceptionAsError(new UnsupportedOperationException(String.format("Unwrap Key Operation is not allowed " - + "for key with id %s", this.key.getId())))); + return Mono.error(logger.logExceptionAsError(new UnsupportedOperationException(String.format( + "Unwrap Key Operation is not allowed for key with id %s", this.key.getId())))); } + return localKeyCryptographyClient.unwrapKeyAsync(algorithm, encryptedKey, context, key); }); } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyClient.java index fbd5a989d526c..790cfe5175367 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyClient.java @@ -81,18 +81,20 @@ public Response getKeyWithResponse(Context context) { * Encrypts an arbitrary sequence of bytes using the configured key. Note that the encrypt operation only supports a * single block of data, the size of which is dependent on the target key and the encryption algorithm to be used. * The encrypt operation is supported for both symmetric keys and asymmetric keys. In case of asymmetric keys public - * portion of the key is used - * for encryption. This operation requires the keys/encrypt permission. + * portion of the key is used for encryption. This operation requires the keys/encrypt permission. * *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the - * specified encrypted content. Possible values for assymetric keys include: + * specified encrypted content. Possible values for asymmetric keys include: * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. * - * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, {@link - * EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, {@link EncryptionAlgorithm#A192CBC A192CBC}, - * {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, {@link EncryptionAlgorithm#A256CBC A256CBC} and - * {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512}

+ * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

* *

Code Samples

*

Encrypts the content. Subscribes to the call asynchronously and prints out the encrypted content details when @@ -104,12 +106,12 @@ public Response getKeyWithResponse(Context context) { * @param context Additional context that is passed through the Http pipeline during the service call. * @return A {@link EncryptResult} whose {@link EncryptResult#getCipherText() cipher text} contains the encrypted * content. - * @throws ResourceNotFoundException if the key cannot be found for encryption. - * @throws UnsupportedOperationException if the encrypt operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code plainText} is null. + * @throws ResourceNotFoundException If the key cannot be found for encryption. + * @throws UnsupportedOperationException If the encrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code plaintext} are {@code null}. */ public EncryptResult encrypt(EncryptionAlgorithm algorithm, byte[] plaintext, Context context) { - return client.encrypt(algorithm, plaintext, context).block(); + return encrypt(new EncryptOptions(algorithm, plaintext, null, null), context); } /** @@ -119,13 +121,17 @@ public EncryptResult encrypt(EncryptionAlgorithm algorithm, byte[] plaintext, Co * portion of the key is used for encryption. This operation requires the keys/encrypt permission. * *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the - * specified encrypted content. Possible values - * for assymetric keys include: {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP - * RSA_OAEP} and {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. - * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, {@link - * EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, - * {@link EncryptionAlgorithm#A192CBC A192CBC}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, {@link - * EncryptionAlgorithm#A256CBC A256CBC} and {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512}

+ * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

* *

Code Samples

*

Encrypts the content. Subscribes to the call asynchronously and prints out the encrypted content details when @@ -135,15 +141,51 @@ public EncryptResult encrypt(EncryptionAlgorithm algorithm, byte[] plaintext, Co * @param algorithm The algorithm to be used for encryption. * @param plaintext The content to be encrypted. * @return The {@link EncryptResult} whose {@link EncryptResult#getCipherText() cipher text} contains the encrypted - * content. - * @throws ResourceNotFoundException if the key cannot be found for encryption. - * @throws UnsupportedOperationException if the encrypt operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code plainText} is null. + * content. + * @throws ResourceNotFoundException If the key cannot be found for encryption. + * @throws UnsupportedOperationException If the encrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code plaintext} are {@code null}. */ public EncryptResult encrypt(EncryptionAlgorithm algorithm, byte[] plaintext) { return encrypt(algorithm, plaintext, Context.NONE); } + /** + * Encrypts an arbitrary sequence of bytes using the configured key. Note that the encrypt operation only supports a + * single block of data, the size of which is dependent on the target key and the encryption algorithm to be used. + * The encrypt operation is supported for both symmetric keys and asymmetric keys. In case of asymmetric keys public + * portion of the key is used for encryption. This operation requires the keys/encrypt permission. + * + *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the + * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

+ * + *

Code Samples

+ *

Encrypts the content. Subscribes to the call asynchronously and prints out the encrypted content details when + * a response has been received.

+ * {@codesnippet com.azure.security.keyvault.keys.cryptography.CryptographyClient.encrypt#EncryptOptions-Context} + * + * @param encryptOptions The parameters to use in the encryption operation. + * @param context Additional context that is passed through the Http pipeline during the service call. + * @return The {@link EncryptResult} whose {@link EncryptResult#getCipherText() cipher text} contains the encrypted + * content. + * @throws ResourceNotFoundException If the key cannot be found for encryption. + * @throws UnsupportedOperationException If the encrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code encryptOptions} is {@code null}. + */ + public EncryptResult encrypt(EncryptOptions encryptOptions, Context context) { + return client.encrypt(encryptOptions, context).block(); + } + /** * Decrypts a single block of encrypted data using the configured key and specified algorithm. Note that only a * single block of data may be decrypted, the size of this block is dependent on the target key and the algorithm to @@ -151,13 +193,17 @@ public EncryptResult encrypt(EncryptionAlgorithm algorithm, byte[] plaintext) { * keys/decrypt permission. * *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the - * specified encrypted content. Possible values - * for assymetric keys include: {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP - * RSA_OAEP} and {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. - * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, {@link - * EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, - * {@link EncryptionAlgorithm#A192CBC A192CBC}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, {@link - * EncryptionAlgorithm#A256CBC A256CBC} and {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512}

+ * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

* *

Code Samples

*

Decrypts the encrypted content. Subscribes to the call asynchronously and prints out the decrypted content @@ -165,15 +211,15 @@ public EncryptResult encrypt(EncryptionAlgorithm algorithm, byte[] plaintext) { * {@codesnippet com.azure.security.keyvault.keys.cryptography.CryptographyClient.decrypt#EncryptionAlgorithm-byte-Context} * * @param algorithm The algorithm to be used for decryption. - * @param cipherText The content to be decrypted. + * @param ciphertext The content to be decrypted. * @param context Additional context that is passed through the Http pipeline during the service call. * @return The decrypted blob. - * @throws ResourceNotFoundException if the key cannot be found for decryption. - * @throws UnsupportedOperationException if the decrypt operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code cipherText} is null. + * @throws ResourceNotFoundException If the key cannot be found for encryption. + * @throws UnsupportedOperationException If the decrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code ciphertext} are {@code null}. */ - public DecryptResult decrypt(EncryptionAlgorithm algorithm, byte[] cipherText, Context context) { - return client.decrypt(algorithm, cipherText, context).block(); + public DecryptResult decrypt(EncryptionAlgorithm algorithm, byte[] ciphertext, Context context) { + return decrypt(new DecryptOptions(algorithm, ciphertext, null, null, null), context); } /** @@ -183,13 +229,17 @@ public DecryptResult decrypt(EncryptionAlgorithm algorithm, byte[] cipherText, C * keys/decrypt permission. * *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the - * specified encrypted content. Possible values - * for assymetric keys include: {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP - * RSA_OAEP} and {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. - * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, {@link - * EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, - * {@link EncryptionAlgorithm#A192CBC A192CBC}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, {@link - * EncryptionAlgorithm#A256CBC A256CBC} and {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512}

+ * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

* *

Code Samples

*

Decrypts the encrypted content. Subscribes to the call asynchronously and prints out the decrypted content @@ -197,14 +247,49 @@ public DecryptResult decrypt(EncryptionAlgorithm algorithm, byte[] cipherText, C * {@codesnippet com.azure.security.keyvault.keys.cryptography.CryptographyClient.decrypt#EncryptionAlgorithm-byte} * * @param algorithm The algorithm to be used for decryption. - * @param cipherText The content to be decrypted. + * @param ciphertext The content to be decrypted. + * @return The decrypted blob. + * @throws ResourceNotFoundException If the key cannot be found for encryption. + * @throws UnsupportedOperationException If the decrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code ciphertext} are {@code null}. + */ + public DecryptResult decrypt(EncryptionAlgorithm algorithm, byte[] ciphertext) { + return decrypt(new DecryptOptions(algorithm, ciphertext, null, null, null), Context.NONE); + } + + /** + * Decrypts a single block of encrypted data using the configured key and specified algorithm. Note that only a + * single block of data may be decrypted, the size of this block is dependent on the target key and the algorithm to + * be used. The decrypt operation is supported for both asymmetric and symmetric keys. This operation requires the + * keys/decrypt permission. + * + *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the + * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

+ * + *

Code Samples

+ *

Decrypts the encrypted content. Subscribes to the call asynchronously and prints out the decrypted content + * details when a response has been received.

+ * {@codesnippet com.azure.security.keyvault.keys.cryptography.CryptographyClient.decrypt#DecryptOptions-Context} + * + * @param decryptOptions The parameters to use in the decryption operation. + * @param context Additional context that is passed through the Http pipeline during the service call. * @return The decrypted blob. - * @throws ResourceNotFoundException if the key cannot be found for decryption. - * @throws UnsupportedOperationException if the decrypt operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code cipherText} is null. + * @throws ResourceNotFoundException If the key cannot be found for encryption. + * @throws UnsupportedOperationException If the decrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code decryptOptions} is {@code null}. */ - public DecryptResult decrypt(EncryptionAlgorithm algorithm, byte[] cipherText) { - return decrypt(algorithm, cipherText, Context.NONE); + public DecryptResult decrypt(DecryptOptions decryptOptions, Context context) { + return client.decrypt(decryptOptions, context).block(); } /** @@ -332,9 +417,12 @@ public VerifyResult verify(SignatureAlgorithm algorithm, byte[] digest, byte[] s * symmetric and asymmetric keys. This operation requires the keys/wrapKey permission. * *

The {@link KeyWrapAlgorithm wrap algorithm} indicates the type of algorithm to use for wrapping the specified - * key content. Possible values include: - * {@link KeyWrapAlgorithm#RSA1_5 RSA1_5}, {@link KeyWrapAlgorithm#RSA_OAEP RSA_OAEP} and {@link - * KeyWrapAlgorithm#RSA_OAEP_256 RSA_OAEP_256}

+ * key content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128KW A128KW}, + * {@link EncryptionAlgorithm#A192KW A192KW} and {@link EncryptionAlgorithm#A256KW A256KW}.

* *

Code Samples

*

Wraps the key content. Subscribes to the call asynchronously and prints out the wrapped key details when a @@ -342,12 +430,12 @@ public VerifyResult verify(SignatureAlgorithm algorithm, byte[] digest, byte[] s * {@codesnippet com.azure.security.keyvault.keys.cryptography.CryptographyClient.wrapKey#KeyWrapAlgorithm-byte} * * @param algorithm The encryption algorithm to use for wrapping the key. - * @param key The key content to be wrapped + * @param key The key content to be wrapped. * @return The {@link WrapResult} whose {@link WrapResult#getEncryptedKey() encrypted key} contains the wrapped - * key result. - * @throws ResourceNotFoundException if the key cannot be found for wrap operation. - * @throws UnsupportedOperationException if the wrap operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code key} is null. + * key result. + * @throws ResourceNotFoundException If the key cannot be found for encryption. + * @throws UnsupportedOperationException If the wrap operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code key} are {@code null}. */ public WrapResult wrapKey(KeyWrapAlgorithm algorithm, byte[] key) { return wrapKey(algorithm, key, Context.NONE); @@ -358,9 +446,12 @@ public WrapResult wrapKey(KeyWrapAlgorithm algorithm, byte[] key) { * symmetric and asymmetric keys. This operation requires the keys/wrapKey permission. * *

The {@link KeyWrapAlgorithm wrap algorithm} indicates the type of algorithm to use for wrapping the specified - * key content. Possible values include: - * {@link KeyWrapAlgorithm#RSA1_5 RSA1_5}, {@link KeyWrapAlgorithm#RSA_OAEP RSA_OAEP} and {@link - * KeyWrapAlgorithm#RSA_OAEP_256 RSA_OAEP_256}

+ * key content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128KW A128KW}, + * {@link EncryptionAlgorithm#A192KW A192KW} and {@link EncryptionAlgorithm#A256KW A256KW}.

* *

Code Samples

*

Wraps the key content. Subscribes to the call asynchronously and prints out the wrapped key details when a @@ -368,13 +459,13 @@ public WrapResult wrapKey(KeyWrapAlgorithm algorithm, byte[] key) { * {@codesnippet com.azure.security.keyvault.keys.cryptography.CryptographyClient.wrapKey#KeyWrapAlgorithm-byte-Context} * * @param algorithm The encryption algorithm to use for wrapping the key. - * @param key The key content to be wrapped + * @param key The key content to be wrapped. * @param context Additional context that is passed through the Http pipeline during the service call. * @return The {@link WrapResult} whose {@link WrapResult#getEncryptedKey() encrypted key} contains the wrapped - * key result. - * @throws ResourceNotFoundException if the key cannot be found for wrap operation. - * @throws UnsupportedOperationException if the wrap operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code key} is null. + * key result. + * @throws ResourceNotFoundException If the key cannot be found for encryption. + * @throws UnsupportedOperationException If the wrap operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code key} are {@code null}. */ public WrapResult wrapKey(KeyWrapAlgorithm algorithm, byte[] key, Context context) { return client.wrapKey(algorithm, key, context).block(); @@ -387,10 +478,11 @@ public WrapResult wrapKey(KeyWrapAlgorithm algorithm, byte[] key, Context contex * *

The {@link KeyWrapAlgorithm wrap algorithm} indicates the type of algorithm to use for wrapping the specified * key content. Possible values for asymmetric keys include: - * {@link KeyWrapAlgorithm#RSA1_5 RSA1_5}, {@link KeyWrapAlgorithm#RSA_OAEP RSA_OAEP} and {@link - * KeyWrapAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. - * Possible values for symmetric keys include: {@link KeyWrapAlgorithm#A128KW A128KW}, {@link - * KeyWrapAlgorithm#A192KW A192KW} and {@link KeyWrapAlgorithm#A256KW A256KW}

+ * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128KW A128KW}, + * {@link EncryptionAlgorithm#A192KW A192KW} and {@link EncryptionAlgorithm#A256KW A256KW}.

* *

Code Samples

*

Unwraps the key content. Subscribes to the call asynchronously and prints out the unwrapped key details when a @@ -400,9 +492,9 @@ public WrapResult wrapKey(KeyWrapAlgorithm algorithm, byte[] key, Context contex * @param algorithm The encryption algorithm to use for wrapping the key. * @param encryptedKey The encrypted key content to unwrap. * @return The unwrapped key content. - * @throws ResourceNotFoundException if the key cannot be found for wrap operation. - * @throws UnsupportedOperationException if the unwrap operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code encryptedKey} is null. + * @throws ResourceNotFoundException If the key cannot be found for wrap operation. + * @throws UnsupportedOperationException If the unwrap operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code encryptedKey} are {@code null}. */ public UnwrapResult unwrapKey(KeyWrapAlgorithm algorithm, byte[] encryptedKey) { return unwrapKey(algorithm, encryptedKey, Context.NONE); @@ -410,16 +502,16 @@ public UnwrapResult unwrapKey(KeyWrapAlgorithm algorithm, byte[] encryptedKey) { /** * Unwraps a symmetric key using the configured key that was initially used for wrapping that key. This operation is - * the reverse of the wrap operation. - * The unwrap operation supports asymmetric and symmetric keys to unwrap. This operation requires the keys/unwrapKey - * permission. + * the reverse of the wrap operation. The unwrap operation supports asymmetric and symmetric keys to unwrap. This + * operation requires the keys/unwrapKey permission. * *

The {@link KeyWrapAlgorithm wrap algorithm} indicates the type of algorithm to use for wrapping the specified * key content. Possible values for asymmetric keys include: - * {@link KeyWrapAlgorithm#RSA1_5 RSA1_5}, {@link KeyWrapAlgorithm#RSA_OAEP RSA_OAEP} and {@link - * KeyWrapAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. - * Possible values for symmetric keys include: {@link KeyWrapAlgorithm#A128KW A128KW}, {@link - * KeyWrapAlgorithm#A192KW A192KW} and {@link KeyWrapAlgorithm#A256KW A256KW}

+ * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128KW A128KW}, + * {@link EncryptionAlgorithm#A192KW A192KW} and {@link EncryptionAlgorithm#A256KW A256KW}.

* *

Code Samples

*

Unwraps the key content. Subscribes to the call asynchronously and prints out the unwrapped key details when a @@ -430,9 +522,9 @@ public UnwrapResult unwrapKey(KeyWrapAlgorithm algorithm, byte[] encryptedKey) { * @param encryptedKey The encrypted key content to unwrap. * @param context Additional context that is passed through the Http pipeline during the service call. * @return The unwrapped key content. - * @throws ResourceNotFoundException if the key cannot be found for wrap operation. - * @throws UnsupportedOperationException if the unwrap operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code encryptedKey} is null. + * @throws ResourceNotFoundException If the key cannot be found for wrap operation. + * @throws UnsupportedOperationException If the unwrap operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code encryptedKey} are {@code null}. */ public UnwrapResult unwrapKey(KeyWrapAlgorithm algorithm, byte[] encryptedKey, Context context) { return client.unwrapKey(algorithm, encryptedKey, context).block(); diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyServiceClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyServiceClient.java index ed4eb2bc3047b..9a4a691d8ff1d 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyServiceClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/CryptographyServiceClient.java @@ -125,10 +125,19 @@ JsonWebKey transformSecretKey(SecretKey secretKey) throws JsonProcessingExceptio return mapper.readValue(jsonString, JsonWebKey.class); } - Mono encrypt(EncryptionAlgorithm algorithm, byte[] plaintext, Context context) { + Mono encrypt(EncryptOptions encryptOptions, Context context) { + Objects.requireNonNull(encryptOptions, "'encryptOptions' cannot be null."); - KeyOperationParameters parameters = new KeyOperationParameters().setAlgorithm(algorithm).setValue(plaintext); + EncryptionAlgorithm algorithm = encryptOptions.getAlgorithm(); + byte[] iv = encryptOptions.getIv(); + byte[] authenticatedData = encryptOptions.getAdditionalAuthenticatedData(); + KeyOperationParameters parameters = new KeyOperationParameters() + .setAlgorithm(algorithm) + .setValue(encryptOptions.getPlaintext()) + .setIv(iv) + .setAdditionalAuthenticatedData(authenticatedData); context = context == null ? Context.NONE : context; + return service.encrypt(vaultUrl, keyName, version, apiVersion, ACCEPT_LANGUAGE, parameters, CONTENT_TYPE_HEADER_VALUE, context.addData(AZ_TRACING_NAMESPACE_KEY, KEYVAULT_TRACING_NAMESPACE_VALUE)) .doOnRequest(ignored -> logger.info("Encrypting content with algorithm - {}", algorithm.toString())) @@ -140,9 +149,21 @@ Mono encrypt(EncryptionAlgorithm algorithm, byte[] plaintext, Con Mono.just(new EncryptResult(keyOperationResultResponse.getValue().getResult(), algorithm, keyId))); } - Mono decrypt(EncryptionAlgorithm algorithm, byte[] cipherText, Context context) { - KeyOperationParameters parameters = new KeyOperationParameters().setAlgorithm(algorithm).setValue(cipherText); + Mono decrypt(DecryptOptions decryptOptions, Context context) { + Objects.requireNonNull(decryptOptions, "'decryptOptions' cannot be null."); + + EncryptionAlgorithm algorithm = decryptOptions.getAlgorithm(); + byte[] iv = decryptOptions.getIv(); + byte[] additionalAuthenticatedData = decryptOptions.getAdditionalAuthenticatedData(); + byte[] authenticationTag = decryptOptions.getAuthenticationTag(); + KeyOperationParameters parameters = new KeyOperationParameters() + .setAlgorithm(algorithm) + .setValue(decryptOptions.getCiphertext()) + .setIv(iv) + .setAdditionalAuthenticatedData(additionalAuthenticatedData) + .setAuthenticationTag(authenticationTag); context = context == null ? Context.NONE : context; + return service.decrypt(vaultUrl, keyName, version, apiVersion, ACCEPT_LANGUAGE, parameters, CONTENT_TYPE_HEADER_VALUE, context.addData(AZ_TRACING_NAMESPACE_KEY, KEYVAULT_TRACING_NAMESPACE_VALUE)) .doOnRequest(ignored -> logger.info("Decrypting content with algorithm - {}", algorithm.toString())) @@ -183,9 +204,11 @@ Mono verify(SignatureAlgorithm algorithm, byte[] digest, byte[] si } Mono wrapKey(KeyWrapAlgorithm algorithm, byte[] key, Context context) { - - KeyWrapUnwrapRequest parameters = new KeyWrapUnwrapRequest().setAlgorithm(algorithm).setValue(key); + KeyWrapUnwrapRequest parameters = new KeyWrapUnwrapRequest() + .setAlgorithm(algorithm) + .setValue(key); context = context == null ? Context.NONE : context; + return service.wrapKey(vaultUrl, keyName, version, apiVersion, ACCEPT_LANGUAGE, parameters, CONTENT_TYPE_HEADER_VALUE, context.addData(AZ_TRACING_NAMESPACE_KEY, KEYVAULT_TRACING_NAMESPACE_VALUE)) .doOnRequest(ignored -> logger.info("Wrapping key content with algorithm - {}", algorithm.toString())) @@ -199,8 +222,11 @@ Mono wrapKey(KeyWrapAlgorithm algorithm, byte[] key, Context context Mono unwrapKey(KeyWrapAlgorithm algorithm, byte[] encryptedKey, Context context) { - KeyWrapUnwrapRequest parameters = new KeyWrapUnwrapRequest().setAlgorithm(algorithm).setValue(encryptedKey); + KeyWrapUnwrapRequest parameters = new KeyWrapUnwrapRequest() + .setAlgorithm(algorithm) + .setValue(encryptedKey); context = context == null ? Context.NONE : context; + return service.unwrapKey(vaultUrl, keyName, version, apiVersion, ACCEPT_LANGUAGE, parameters, CONTENT_TYPE_HEADER_VALUE, context.addData(AZ_TRACING_NAMESPACE_KEY, KEYVAULT_TRACING_NAMESPACE_VALUE)) .doOnRequest(ignored -> logger.info("Unwrapping key content with algorithm - {}", algorithm.toString())) diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/DecryptOptions.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/DecryptOptions.java new file mode 100644 index 0000000000000..54dd9a8246e5b --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/DecryptOptions.java @@ -0,0 +1,261 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.cryptography; + +import com.azure.core.util.CoreUtils; +import com.azure.security.keyvault.keys.cryptography.models.EncryptionAlgorithm; + +import java.util.Objects; + +/** + * A class containing various configuration parameters that can be applied when performing decryption operations. + */ +public class DecryptOptions { + /** + * The algorithm to be used for decryption. + */ + private final EncryptionAlgorithm algorithm; + + /** + * The content to be decrypted. + */ + private final byte[] ciphertext; + + /** + * Initialization vector to be used in the decryption operation using a symmetric algorithm. + */ + private final byte[] iv; + + /** + * Get additional data to authenticate when performing decryption with an authenticated algorithm. + */ + private final byte[] additionalAuthenticatedData; + + /** + * The tag to authenticate when performing decryption with an authenticated algorithm. + */ + private final byte[] authenticationTag; + + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A128CBC}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes128CbcOptions(byte[] ciphertext, byte[] iv) { + return new DecryptOptions(EncryptionAlgorithm.A128CBC, ciphertext, iv, null, null); + } + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A128CBCPAD}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes128CbcPadOptions(byte[] ciphertext, byte[] iv) { + return new DecryptOptions(EncryptionAlgorithm.A128CBCPAD, ciphertext, iv, null, null); + } + + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A128GCM}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @param authenticationTag The tag to authenticate when performing decryption. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes128GcmOptions(byte[] ciphertext, byte[] iv, byte[] authenticationTag) { + return createAes128GcmOptions(ciphertext, iv, authenticationTag, null); + } + + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A128GCM}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @param authenticationTag The tag to authenticate when performing decryption. + * @param additionalAuthenticatedData Additional data to authenticate when using authenticated crypto algorithms. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes128GcmOptions(byte[] ciphertext, byte[] iv, byte[] authenticationTag, + byte[] additionalAuthenticatedData) { + return new DecryptOptions(EncryptionAlgorithm.A128GCM, ciphertext, iv, authenticationTag, + additionalAuthenticatedData); + } + + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A192CBC}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes192CbcOptions(byte[] ciphertext, byte[] iv) { + return new DecryptOptions(EncryptionAlgorithm.A192CBC, ciphertext, iv, null, null); + } + + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A192CBCPAD}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes192CbcPadOptions(byte[] ciphertext, byte[] iv) { + return new DecryptOptions(EncryptionAlgorithm.A192CBCPAD, ciphertext, iv, null, null); + } + + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A192GCM}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @param authenticationTag The tag to authenticate when performing decryption. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes192GcmOptions(byte[] ciphertext, byte[] iv, byte[] authenticationTag) { + return createAes192GcmOptions(ciphertext, iv, authenticationTag, null); + } + + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A192GCM}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @param authenticationTag The tag to authenticate when performing decryption. + * @param additionalAuthenticatedData Additional data to authenticate when using authenticated crypto algorithms. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes192GcmOptions(byte[] ciphertext, byte[] iv, byte[] authenticationTag, + byte[] additionalAuthenticatedData) { + return new DecryptOptions(EncryptionAlgorithm.A192GCM, ciphertext, iv, authenticationTag, + additionalAuthenticatedData); + } + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A256CBC}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes256CbcOptions(byte[] ciphertext, byte[] iv) { + return new DecryptOptions(EncryptionAlgorithm.A256CBC, ciphertext, iv, null, null); + } + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A256CBCPAD}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes256CbcPadOptions(byte[] ciphertext, byte[] iv) { + return new DecryptOptions(EncryptionAlgorithm.A256CBCPAD, ciphertext, iv, null, null); + } + + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A256GCM}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @param authenticationTag The tag to authenticate when performing decryption. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes256GcmOptions(byte[] ciphertext, byte[] iv, byte[] authenticationTag) { + return createAes256GcmOptions(ciphertext, iv, authenticationTag, null); + } + + /** + * Factory method to create an instance of {@link DecryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A256GCM}. + * + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @param authenticationTag The tag to authenticate when performing decryption. + * @param additionalAuthenticatedData Additional data to authenticate when using authenticated crypto algorithms. + * @return The {@link DecryptOptions}. + */ + public static DecryptOptions createAes256GcmOptions(byte[] ciphertext, byte[] iv, byte[] authenticationTag, + byte[] additionalAuthenticatedData) { + return new DecryptOptions(EncryptionAlgorithm.A256GCM, ciphertext, iv, authenticationTag, + additionalAuthenticatedData); + } + + /** + * Creates an instance of {@link DecryptOptions} with the given parameters. + * + * @param algorithm The algorithm to be used for decryption. + * @param ciphertext The content to be decrypted. + * @param iv Initialization vector for the decryption operation. + * @param authenticationTag The tag to authenticate when performing decryption. + * @param additionalAuthenticatedData Additional data to authenticate when using authenticated crypto algorithms. + */ + DecryptOptions(EncryptionAlgorithm algorithm, byte[] ciphertext, byte[] iv, byte[] authenticationTag, + byte[] additionalAuthenticatedData) { + Objects.requireNonNull(algorithm, "Encryption algorithm cannot be null."); + Objects.requireNonNull(ciphertext, "Cipher text content to be decrypted cannot be null."); + + this.algorithm = algorithm; + this.ciphertext = CoreUtils.clone(ciphertext); + this.iv = CoreUtils.clone(iv); + this.additionalAuthenticatedData = CoreUtils.clone(additionalAuthenticatedData); + this.authenticationTag = CoreUtils.clone(authenticationTag); + } + + /** + * The algorithm to be used for decryption. + * + * @return The algorithm to be used for decryption. + */ + public EncryptionAlgorithm getAlgorithm() { + return algorithm; + } + + /** + * Get the content to be decrypted. + * + * @return The content to be decrypted. + */ + public byte[] getCiphertext() { + return CoreUtils.clone(ciphertext); + } + + /** + * Get the initialization vector to be used in the decryption operation using a symmetric algorithm. + * + * @return The initialization vector. + */ + public byte[] getIv() { + return CoreUtils.clone(iv); + } + + /** + * Get additional data to authenticate when performing decryption with an authenticated algorithm. + * + * @return The additional authenticated data. + */ + public byte[] getAdditionalAuthenticatedData() { + return CoreUtils.clone(additionalAuthenticatedData); + } + + /** + * Get the tag to authenticate when performing decryption with an authenticated algorithm. + * + * @return The authentication tag. + */ + public byte[] getAuthenticationTag() { + return CoreUtils.clone(authenticationTag); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/EcKeyCryptographyClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/EcKeyCryptographyClient.java index 10119b94b6ec7..89a18684f3304 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/EcKeyCryptographyClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/EcKeyCryptographyClient.java @@ -6,7 +6,6 @@ import com.azure.core.util.Context; import com.azure.core.util.logging.ClientLogger; import com.azure.security.keyvault.keys.cryptography.models.DecryptResult; -import com.azure.security.keyvault.keys.cryptography.models.EncryptionAlgorithm; import com.azure.security.keyvault.keys.cryptography.models.EncryptResult; import com.azure.security.keyvault.keys.cryptography.models.UnwrapResult; import com.azure.security.keyvault.keys.cryptography.models.KeyWrapAlgorithm; @@ -56,14 +55,13 @@ private KeyPair getKeyPair(JsonWebKey key) { } @Override - Mono encryptAsync(EncryptionAlgorithm algorithm, byte[] plaintext, Context context, JsonWebKey key) { + Mono encryptAsync(EncryptOptions options, Context context, JsonWebKey key) { throw logger.logExceptionAsError(new UnsupportedOperationException( "Encrypt operation is not supported for EC key")); } @Override - Mono decryptAsync(EncryptionAlgorithm algorithm, byte[] cipherText, Context context, - JsonWebKey key) { + Mono decryptAsync(DecryptOptions options, Context context, JsonWebKey key) { throw logger.logExceptionAsError(new UnsupportedOperationException( "Decrypt operation is not supported for EC key")); } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/EncryptOptions.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/EncryptOptions.java new file mode 100644 index 0000000000000..92e551609cf31 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/EncryptOptions.java @@ -0,0 +1,304 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.cryptography; + +import com.azure.core.util.CoreUtils; +import com.azure.security.keyvault.keys.cryptography.models.EncryptionAlgorithm; + +import java.util.Objects; + +/** + * A class containing various configuration parameters that can be applied when performing encryption operations. + */ +public class EncryptOptions { + /** + * The algorithm to be used for encryption. + */ + private final EncryptionAlgorithm algorithm; + + /** + * The content to be encrypted. + */ + private final byte[] plaintext; + + /** + * Initialization vector to be used in the encryption operation using a symmetric algorithm. + */ + private final byte[] iv; + + /** + * Get additional data to authenticate when performing encryption with an authenticated algorithm. + */ + private final byte[] additionalAuthenticatedData; + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A128CBC}. + * + * @param plaintext The content to be encryption. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes128CbcOptions(byte[] plaintext) { + return createAes128CbcOptions(plaintext, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A128CBC}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes128CbcOptions(byte[] plaintext, byte[] iv) { + return new EncryptOptions(EncryptionAlgorithm.A128CBC, plaintext, iv, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A128CBCPAD}. + * + * @param plaintext The content to be encryption. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes128CbcPadOptions(byte[] plaintext) { + return createAes128CbcPadOptions(plaintext, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A128CBCPAD}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes128CbcPadOptions(byte[] plaintext, byte[] iv) { + return new EncryptOptions(EncryptionAlgorithm.A128CBCPAD, plaintext, iv, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A128GCM}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes128GcmOptions(byte[] plaintext, byte[] iv) { + return createAes128GcmOptions(plaintext, iv, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A128GCM}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @param additionalAuthenticatedData Additional data to authenticate when using authenticated crypto algorithms. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes128GcmOptions(byte[] plaintext, byte[] iv, + byte[] additionalAuthenticatedData) { + return new EncryptOptions(EncryptionAlgorithm.A128GCM, plaintext, iv, additionalAuthenticatedData); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A192CBC}. + * + * @param plaintext The content to be encryption. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes192CbcOptions(byte[] plaintext) { + return createAes192CbcOptions(plaintext, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A192CBC}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes192CbcOptions(byte[] plaintext, byte[] iv) { + return new EncryptOptions(EncryptionAlgorithm.A192CBC, plaintext, iv, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A192CBCPAD}. + * + * @param plaintext The content to be encryption. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes192CbcPadOptions(byte[] plaintext) { + return createAes192CbcPadOptions(plaintext, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A192CBCPAD}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes192CbcPadOptions(byte[] plaintext, byte[] iv) { + return new EncryptOptions(EncryptionAlgorithm.A192CBCPAD, plaintext, iv, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A192GCM}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes192GcmOptions(byte[] plaintext, byte[] iv) { + return createAes192GcmOptions(plaintext, iv, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A192GCM}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @param additionalAuthenticatedData Additional data to authenticate when using authenticated crypto algorithms. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes192GcmOptions(byte[] plaintext, byte[] iv, + byte[] additionalAuthenticatedData) { + return new EncryptOptions(EncryptionAlgorithm.A192GCM, plaintext, iv, additionalAuthenticatedData); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A256CBC}. + * + * @param plaintext The content to be encryption. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes256CbcOptions(byte[] plaintext) { + return createAes256CbcOptions(plaintext, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A256CBC}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes256CbcOptions(byte[] plaintext, byte[] iv) { + return new EncryptOptions(EncryptionAlgorithm.A256CBC, plaintext, iv, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A256CBCPAD}. + * + * @param plaintext The content to be encryption. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes256CbcPadOptions(byte[] plaintext) { + return createAes256CbcPadOptions(plaintext, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A256CBCPAD}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes256CbcPadOptions(byte[] plaintext, byte[] iv) { + return new EncryptOptions(EncryptionAlgorithm.A256CBCPAD, plaintext, iv, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A256GCM}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes256GcmOptions(byte[] plaintext, byte[] iv) { + return createAes256GcmOptions(plaintext, iv, null); + } + + /** + * Factory method to create an instance of {@link EncryptOptions} with the given parameters for + * {@link EncryptionAlgorithm#A256GCM}. + * + * @param plaintext The content to be encryption. + * @param iv Initialization vector for the encryption operation. + * @param additionalAuthenticatedData Additional data to authenticate when using authenticated crypto algorithms. + * @return The {@link EncryptOptions}. + */ + public static EncryptOptions createAes256GcmOptions(byte[] plaintext, byte[] iv, + byte[] additionalAuthenticatedData) { + return new EncryptOptions(EncryptionAlgorithm.A256GCM, plaintext, iv, additionalAuthenticatedData); + } + + /** + * Creates an instance of {@link EncryptOptions} with the given parameters. + * + * @param algorithm The algorithm to be used for encryption. + * @param plaintext The content to be encrypted. + * @param iv Initialization vector for the encryption operation. + * @param additionalAuthenticatedData Additional data to authenticate when using authenticated crypto algorithms. + */ + EncryptOptions(EncryptionAlgorithm algorithm, byte[] plaintext, byte[] iv, byte[] additionalAuthenticatedData) { + Objects.requireNonNull(algorithm, "Encryption algorithm cannot be null."); + Objects.requireNonNull(plaintext, "Plain text content to be encrypted cannot be null."); + + this.algorithm = algorithm; + this.plaintext = CoreUtils.clone(plaintext); + this.iv = CoreUtils.clone(iv); + this.additionalAuthenticatedData = CoreUtils.clone(additionalAuthenticatedData); + } + + /** + * The algorithm to be used for encryption. + * + * @return The algorithm to be used for encryption. + */ + public EncryptionAlgorithm getAlgorithm() { + return algorithm; + } + + /** + * Get the content to be encrypted. + * + * @return The content to be encrypted. + */ + public byte[] getPlaintext() { + return CoreUtils.clone(plaintext); + } + + /** + * Get the initialization vector to be used in the encryption operation using a symmetric algorithm. + * + * @return The initialization vector. + */ + public byte[] getIv() { + return CoreUtils.clone(iv); + } + + /** + * Get additional data to authenticate when performing encryption with an authenticated algorithm. + * + * @return The additional authenticated data. + */ + public byte[] getAdditionalAuthenticatedData() { + return CoreUtils.clone(additionalAuthenticatedData); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/KeyOperationParameters.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/KeyOperationParameters.java index 261d592039937..ddc794985cd1f 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/KeyOperationParameters.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/KeyOperationParameters.java @@ -24,6 +24,24 @@ class KeyOperationParameters { @JsonProperty(value = "value", required = true) private Base64Url value; + /** + * Initialization vector for symmetric algorithms. + */ + @JsonProperty(value = "iv") + private byte[] iv; + + /** + * Additional data to authenticate but not encrypt/decrypt when using authenticated crypto algorithms. + */ + @JsonProperty(value = "aad") + private byte[] additionalAuthenticatedData; + + /** + * The tag to authenticate when performing decryption with an authenticated algorithm. + */ + @JsonProperty(value = "tag") + private byte[] authenticationTag; + /** * Get the algorithm value. * @@ -71,4 +89,63 @@ public KeyOperationParameters setValue(byte[] value) { return this; } + /** + * Get the initialization vector to be used in the cryptographic operation using a symmetric algorithm. + * + * @return The initialization vector. + */ + public byte[] getIv() { + return iv; + } + + /** + * Set the initialization vector to be used in the cryptographic operation using a symmetric algorithm. + * + * @param iv The initialization vector to set. + * @return The updated {@link KeyOperationParameters} object. + */ + public KeyOperationParameters setIv(byte[] iv) { + this.iv = iv; + return this; + } + + /** + * Get additional data to authenticate but not encrypt/decrypt when using authenticated crypto algorithms. + * + * @return The additional authenticated data. + */ + public byte[] getAdditionalAuthenticatedData() { + return additionalAuthenticatedData; + } + + /** + * Set additional data to authenticate but not encrypt/decrypt when using authenticated crypto algorithms. + * + * @param additionalAuthenticatedData The additional authenticated data. + * @return The updated {@link KeyOperationParameters} object. + */ + public KeyOperationParameters setAdditionalAuthenticatedData(byte[] additionalAuthenticatedData) { + this.additionalAuthenticatedData = additionalAuthenticatedData; + return this; + } + + /** + * Get the tag to authenticate when performing decryption with an authenticated algorithm. + * + * @return The authentication tag. + */ + public byte[] getAuthenticationTag() { + return authenticationTag; + } + + /** + * Set the tag to authenticate when performing decryption with an authenticated algorithm. + * + * @param authenticationTag The tag to set. + * @return The updated {@link KeyOperationParameters} object. + */ + public KeyOperationParameters setAuthenticationTag(byte[] authenticationTag) { + this.authenticationTag = authenticationTag; + return this; + } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/KeyWrapUnwrapRequest.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/KeyWrapUnwrapRequest.java index 31a2e1f8d86a3..d1045cfdf3a4a 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/KeyWrapUnwrapRequest.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/KeyWrapUnwrapRequest.java @@ -70,5 +70,4 @@ public KeyWrapUnwrapRequest setValue(byte[] value) { } return this; } - } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyAsyncClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyAsyncClient.java index eed5f8cf74da5..491f212e49b41 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyAsyncClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyAsyncClient.java @@ -48,8 +48,17 @@ Mono getKeyId() { * portion of the key is used for encryption. This operation requires the keys/encrypt permission. * *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for encrypting the - * specified {@code plaintext}. Possible values for assymetric keys include: - * {@link EncryptionAlgorithm#RSA1_5 RSA1_5} and {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP}.

+ * specified {@code plaintext}. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

* *

Code Samples

*

Encrypts the content. Subscribes to the call asynchronously and prints out the encrypted content details when @@ -60,13 +69,46 @@ Mono getKeyId() { * @param plaintext The content to be encrypted. * @return A {@link Mono} containing a {@link EncryptResult} whose {@link EncryptResult#getCipherText() cipher text} * contains the encrypted content. - * @throws UnsupportedOperationException if the encrypt operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code plainText} is null. + * @throws UnsupportedOperationException If the encrypt operation is not supported or configured on the key. + * @throws NullPointerException if {@code algorithm} or {@code plaintext} is {@code null}. */ public Mono encrypt(EncryptionAlgorithm algorithm, byte[] plaintext) { return cryptographyAsyncClient.encrypt(algorithm, plaintext); } + /** + * Encrypts an arbitrary sequence of bytes using the configured key. Note that the encrypt operation only supports a + * single block of data, the size of which is dependent on the target key and the encryption algorithm to be used. + * The encrypt operation is supported for both symmetric keys and asymmetric keys. In case of asymmetric keys public + * portion of the key is used for encryption. This operation requires the keys/encrypt permission. + * + *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for encrypting the + * specified {@code plaintext}. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

+ * + *

Code Samples

+ *

Encrypts the content. Subscribes to the call asynchronously and prints out the encrypted content details when + * a response has been received.

+ * {@codesnippet com.azure.security.keyvault.keys.cryptography.LocalCryptographyAsyncClient.encrypt#EncryptOptions} + * + * @param encryptOptions The parameters to use in the encryption operation. + * @return A {@link Mono} containing a {@link EncryptResult} whose {@link EncryptResult#getCipherText() cipher text} + * contains the encrypted content. + * @throws UnsupportedOperationException If the encrypt operation is not supported or configured on the key. + * @throws NullPointerException if {@code encryptOptions} is {@code null}. + */ + public Mono encrypt(EncryptOptions encryptOptions) { + return cryptographyAsyncClient.encrypt(encryptOptions); + } /** * Decrypts a single block of encrypted data using the configured key and specified algorithm. Note that only a @@ -75,8 +117,17 @@ public Mono encrypt(EncryptionAlgorithm algorithm, byte[] plainte * keys/decrypt permission. * *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the - * specified encrypted content. Possible values for assymetric keys include: - * {@link EncryptionAlgorithm#RSA1_5 RSA1_5} and {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP}.

+ * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and {@link + * EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

* *

Code Samples

*

Decrypts the encrypted content. Subscribes to the call asynchronously and prints out the decrypted content @@ -84,13 +135,46 @@ public Mono encrypt(EncryptionAlgorithm algorithm, byte[] plainte * {@codesnippet com.azure.security.keyvault.keys.cryptography.LocalCryptographyAsyncClient.decrypt#EncryptionAlgorithm-byte} * * @param algorithm The algorithm to be used for decryption. - * @param cipherText The content to be decrypted. + * @param ciphertext The content to be decrypted. + * @return A {@link Mono} containing the decrypted blob. + * @throws UnsupportedOperationException If the decrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code ciphertext} are {@code null}. + */ + public Mono decrypt(EncryptionAlgorithm algorithm, byte[] ciphertext) { + return cryptographyAsyncClient.decrypt(algorithm, ciphertext); + } + + /** + * Decrypts a single block of encrypted data using the configured key and specified algorithm. Note that only a + * single block of data may be decrypted, the size of this block is dependent on the target key and the algorithm to + * be used. The decrypt operation is supported for both asymmetric and symmetric keys. This operation requires the + * keys/decrypt permission. + * + *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the + * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and {@link + * EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

+ * + *

Code Samples

+ *

Decrypts the encrypted content. Subscribes to the call asynchronously and prints out the decrypted content + * details when a response has been received.

+ * {@codesnippet com.azure.security.keyvault.keys.cryptography.LocalCryptographyAsyncClient.decrypt#DecryptOptions} + * + * @param decryptOptions The parameters to use in the decryption operation. * @return A {@link Mono} containing the decrypted blob. - * @throws UnsupportedOperationException if the decrypt operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code cipherText} is null. + * @throws UnsupportedOperationException If the decrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code decryptOptions} is {@code null}. */ - public Mono decrypt(EncryptionAlgorithm algorithm, byte[] cipherText) { - return cryptographyAsyncClient.decrypt(algorithm, cipherText); + public Mono decrypt(DecryptOptions decryptOptions) { + return cryptographyAsyncClient.decrypt(decryptOptions); } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClient.java index 3a94bf613899b..2c55c84bfc0c4 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClient.java @@ -44,9 +44,17 @@ public class LocalCryptographyClient { * portion of the key is used for encryption. This operation requires the keys/encrypt permission. * *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the - * specified encrypted content. Possible values - * for assymetric keys include: {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP - * RSA_OAEP}.

+ * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

* *

Code Samples

*

Encrypts the content. Subscribes to the call asynchronously and prints out the encrypted content details when @@ -57,13 +65,47 @@ public class LocalCryptographyClient { * @param plaintext The content to be encrypted. * @return The {@link EncryptResult} whose {@link EncryptResult#getCipherText() cipher text} contains the encrypted * content. - * @throws UnsupportedOperationException if the encrypt operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code plainText} is null. + * @throws UnsupportedOperationException If the encrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code decryptOptions} or {@code plaintext} is {@code null}. */ public EncryptResult encrypt(EncryptionAlgorithm algorithm, byte[] plaintext) { return client.encrypt(algorithm, plaintext).block(); } + /** + * Encrypts an arbitrary sequence of bytes using the configured key. Note that the encrypt operation only supports a + * single block of data, the size of which is dependent on the target key and the encryption algorithm to be used. + * The encrypt operation is supported for both symmetric keys and asymmetric keys. In case of asymmetric keys public + * portion of the key is used for encryption. This operation requires the keys/encrypt permission. + * + *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the + * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and + * {@link EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

+ * + *

Code Samples

+ *

Encrypts the content. Subscribes to the call asynchronously and prints out the encrypted content details when + * a response has been received.

+ * {@codesnippet com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.encrypt#EncryptOptions} + * + * @param encryptOptions The parameters to use in the encryption operation. + * @return The {@link EncryptResult} whose {@link EncryptResult#getCipherText() cipher text} contains the encrypted + * content. + * @throws UnsupportedOperationException If the encrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code decryptOptions} is {@code null}. + */ + public EncryptResult encrypt(EncryptOptions encryptOptions) { + return client.encrypt(encryptOptions).block(); + } + /** * Decrypts a single block of encrypted data using the configured key and specified algorithm. Note that only a * single block of data may be decrypted, the size of this block is dependent on the target key and the algorithm to @@ -71,9 +113,17 @@ public EncryptResult encrypt(EncryptionAlgorithm algorithm, byte[] plaintext) { * keys/decrypt permission. * *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the - * specified encrypted content. Possible values - * for assymetric keys include: {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP - * RSA_OAEP}.

+ * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and {@link + * EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

* *

Code Samples

*

Decrypts the encrypted content. Subscribes to the call asynchronously and prints out the decrypted content @@ -81,13 +131,46 @@ public EncryptResult encrypt(EncryptionAlgorithm algorithm, byte[] plaintext) { * {@codesnippet com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.decrypt#EncryptionAlgorithm-byte} * * @param algorithm The algorithm to be used for decryption. - * @param cipherText The content to be decrypted. + * @param ciphertext The content to be decrypted. + * @return The decrypted blob. + * @throws UnsupportedOperationException If the decrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code algorithm} or {@code ciphertext} is {@code null}. + */ + public DecryptResult decrypt(EncryptionAlgorithm algorithm, byte[] ciphertext) { + return client.decrypt(algorithm, ciphertext).block(); + } + + /** + * Decrypts a single block of encrypted data using the configured key and specified algorithm. Note that only a + * single block of data may be decrypted, the size of this block is dependent on the target key and the algorithm to + * be used. The decrypt operation is supported for both asymmetric and symmetric keys. This operation requires the + * keys/decrypt permission. + * + *

The {@link EncryptionAlgorithm encryption algorithm} indicates the type of algorithm to use for decrypting the + * specified encrypted content. Possible values for asymmetric keys include: + * {@link EncryptionAlgorithm#RSA1_5 RSA1_5}, {@link EncryptionAlgorithm#RSA_OAEP RSA_OAEP} and {@link + * EncryptionAlgorithm#RSA_OAEP_256 RSA_OAEP_256}. + * + * Possible values for symmetric keys include: {@link EncryptionAlgorithm#A128CBC A128CBC}, + * {@link EncryptionAlgorithm#A128CBCPAD A128CBCPAD}, {@link EncryptionAlgorithm#A128CBC_HS256 A128CBC-HS256}, + * {@link EncryptionAlgorithm#A128GCM A128GCM}, {@link EncryptionAlgorithm#A192CBC A192CBC}, + * {@link EncryptionAlgorithm#A192CBCPAD A192CBCPAD}, {@link EncryptionAlgorithm#A192CBC_HS384 A192CBC-HS384}, + * {@link EncryptionAlgorithm#A192GCM A192GCM}, {@link EncryptionAlgorithm#A256CBC A256CBC}, + * {@link EncryptionAlgorithm#A256CBCPAD A256CBPAD}, {@link EncryptionAlgorithm#A256CBC_HS512 A256CBC-HS512} and + * {@link EncryptionAlgorithm#A256GCM A256GCM}.

+ * + *

Code Samples

+ *

Decrypts the encrypted content. Subscribes to the call asynchronously and prints out the decrypted content + * details when a response has been received.

+ * {@codesnippet com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.decrypt#DecryptOptions} + * + * @param decryptOptions The parameters to use in the decryption operation. * @return The decrypted blob. - * @throws UnsupportedOperationException if the decrypt operation is not supported or configured on the key. - * @throws NullPointerException if {@code algorithm} or {@code cipherText} is null. + * @throws UnsupportedOperationException If the decrypt operation is not supported or configured on the key. + * @throws NullPointerException If {@code decryptOptions} is {@code null}. */ - public DecryptResult decrypt(EncryptionAlgorithm algorithm, byte[] cipherText) { - return client.decrypt(algorithm, cipherText).block(); + public DecryptResult decrypt(DecryptOptions decryptOptions) { + return client.decrypt(decryptOptions).block(); } /** diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalKeyCryptographyClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalKeyCryptographyClient.java index 281d40cf5bb5c..83ce109bf0e44 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalKeyCryptographyClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/LocalKeyCryptographyClient.java @@ -5,7 +5,6 @@ import com.azure.core.util.Context; import com.azure.security.keyvault.keys.cryptography.models.DecryptResult; -import com.azure.security.keyvault.keys.cryptography.models.EncryptionAlgorithm; import com.azure.security.keyvault.keys.cryptography.models.EncryptResult; import com.azure.security.keyvault.keys.cryptography.models.UnwrapResult; import com.azure.security.keyvault.keys.cryptography.models.KeyWrapAlgorithm; @@ -27,10 +26,9 @@ abstract class LocalKeyCryptographyClient { this.serviceClient = serviceClient; } - abstract Mono encryptAsync(EncryptionAlgorithm algorithm, byte[] plaintext, Context context, JsonWebKey jsonWebKey); + abstract Mono encryptAsync(EncryptOptions encryptOptions, Context context, JsonWebKey jsonWebKey); - abstract Mono decryptAsync(EncryptionAlgorithm algorithm, byte[] cipherText, Context context, - JsonWebKey jsonWebKey); + abstract Mono decryptAsync(DecryptOptions decryptOptions, Context context, JsonWebKey jsonWebKey); abstract Mono signAsync(SignatureAlgorithm algorithm, byte[] digest, Context context, JsonWebKey key); diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/RsaKeyCryptographyClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/RsaKeyCryptographyClient.java index c1dec49478df6..98827d4ab14d8 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/RsaKeyCryptographyClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/RsaKeyCryptographyClient.java @@ -25,6 +25,7 @@ import java.security.KeyPair; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Objects; class RsaKeyCryptographyClient extends LocalKeyCryptographyClient { private KeyPair keyPair; @@ -52,16 +53,20 @@ private KeyPair getKeyPair(JsonWebKey key) { } @Override - Mono encryptAsync(EncryptionAlgorithm algorithm, byte[] plaintext, Context context, - JsonWebKey jsonWebKey) { + Mono encryptAsync(EncryptOptions encryptOptions, Context context, JsonWebKey jsonWebKey) { + Objects.requireNonNull(encryptOptions, "'encryptOptions' cannot be null."); + Objects.requireNonNull(encryptOptions.getAlgorithm(), "Encryption algorithm cannot be null."); + Objects.requireNonNull(encryptOptions.getPlaintext(), "Plain text content to be encrypted cannot be null."); + keyPair = getKeyPair(jsonWebKey); // Interpret the requested algorithm + EncryptionAlgorithm algorithm = encryptOptions.getAlgorithm(); Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm.toString()); if (baseAlgorithm == null) { if (serviceCryptoAvailable()) { - return serviceClient.encrypt(algorithm, plaintext, context); + return serviceClient.encrypt(encryptOptions, context); } return Mono.error(new NoSuchAlgorithmException(algorithm.toString())); } else if (!(baseAlgorithm instanceof AsymmetricEncryptionAlgorithm)) { @@ -70,7 +75,7 @@ Mono encryptAsync(EncryptionAlgorithm algorithm, byte[] plaintext if (keyPair.getPublic() == null) { if (serviceCryptoAvailable()) { - return serviceClient.encrypt(algorithm, plaintext, context); + return serviceClient.encrypt(encryptOptions, context); } return Mono.error(new IllegalArgumentException( "Public portion of the key not available to perform encrypt operation")); @@ -82,7 +87,8 @@ Mono encryptAsync(EncryptionAlgorithm algorithm, byte[] plaintext try { transform = algo.createEncryptor(keyPair); - return Mono.just(new EncryptResult(transform.doFinal(plaintext), algorithm, jsonWebKey.getId())); + return Mono.just(new EncryptResult(transform.doFinal(encryptOptions.getPlaintext()), algorithm, + jsonWebKey.getId())); } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException @@ -93,16 +99,20 @@ Mono encryptAsync(EncryptionAlgorithm algorithm, byte[] plaintext } @Override - Mono decryptAsync(EncryptionAlgorithm algorithm, byte[] cipherText, Context context, - JsonWebKey jsonWebKey) { + Mono decryptAsync(DecryptOptions decryptOptions, Context context, JsonWebKey jsonWebKey) { + Objects.requireNonNull(decryptOptions, "'decryptOptions' cannot be null."); + Objects.requireNonNull(decryptOptions.getAlgorithm(), "Encryption algorithm cannot be null."); + Objects.requireNonNull(decryptOptions.getCiphertext(), "Cipher text content to be decrypted cannot be null."); keyPair = getKeyPair(jsonWebKey); + // Interpret the requested algorithm + EncryptionAlgorithm algorithm = decryptOptions.getAlgorithm(); Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm.toString()); if (baseAlgorithm == null) { if (serviceCryptoAvailable()) { - return serviceClient.decrypt(algorithm, cipherText, context); + return serviceClient.decrypt(decryptOptions, context); } return Mono.error(new NoSuchAlgorithmException(algorithm.toString())); } else if (!(baseAlgorithm instanceof AsymmetricEncryptionAlgorithm)) { @@ -111,7 +121,7 @@ Mono decryptAsync(EncryptionAlgorithm algorithm, byte[] cipherTex if (keyPair.getPrivate() == null) { if (serviceCryptoAvailable()) { - return serviceClient.decrypt(algorithm, cipherText, context); + return serviceClient.decrypt(decryptOptions, context); } return Mono.error(new IllegalArgumentException( "Private portion of the key not available to perform decrypt operation")); @@ -123,7 +133,8 @@ Mono decryptAsync(EncryptionAlgorithm algorithm, byte[] cipherTex try { transform = algo.createDecryptor(keyPair); - return Mono.just(new DecryptResult(transform.doFinal(cipherText), algorithm, jsonWebKey.getId())); + return Mono.just(new DecryptResult(transform.doFinal(decryptOptions.getCiphertext()), algorithm, + jsonWebKey.getId())); } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException @@ -156,7 +167,6 @@ Mono verifyAsync(SignatureAlgorithm algorithm, byte[] digest, byte @Override Mono wrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] key, Context context, JsonWebKey jsonWebKey) { - keyPair = getKeyPair(jsonWebKey); Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm.toString()); @@ -197,7 +207,6 @@ Mono wrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] key, Context co @Override Mono unwrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] encryptedKey, Context context, JsonWebKey jsonWebKey) { - keyPair = getKeyPair(jsonWebKey); // Interpret the requested algorithm diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/SymmetricEncryptionAlgorithm.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/SymmetricEncryptionAlgorithm.java index 4bb18a0afc31e..5d2a5225fd130 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/SymmetricEncryptionAlgorithm.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/SymmetricEncryptionAlgorithm.java @@ -11,10 +11,8 @@ /** * Abstract base class for all symmetric encryption implementation. - * */ abstract class SymmetricEncryptionAlgorithm extends LocalEncryptionAlgorithm { - /* * Constructor. * @@ -25,79 +23,68 @@ abstract class SymmetricEncryptionAlgorithm extends LocalEncryptionAlgorithm { } /* - * Creates a {@link ICryptoTransform} implementation for encryption - * using the supplied initialization vector and the specific provider for the Java Security API. - * @param key - * The key material to be used. - * @param iv - * The initialization vector to be used. - * @param authenticationData - * The authentication data to be used with authenticating encryption implementation (ignored for - * non-authenticating implementation) - * @return A {@link ICryptoTransform} implementation + * Creates a {@link ICryptoTransform} implementation for encryption using the supplied initialization vector and the + * specific provider for the Java Security API. + * + * @param key The key material to be used. + * @param iv The initialization vector to be used. + * @param additionalAuthenticatedData The authentication data to be used with authenticating encryption implementation + * (ignored for non-authenticating implementation). + * @return A {@link ICryptoTransform} implementation. */ - abstract ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] authenticationData) + abstract ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException; /* * Creates a {@link ICryptoTransform} implementation for encryption * using the supplied initialization vector and the specific provider for the Java Security API. - * @param key - * The key material to be used. - * @param iv - * The initialization vector to be used. - * @param authenticationData - * The authentication data to be used with authenticating encryption implementation (ignored for - * non-authenticating implementation) - * @param provider - * The provider to use. - * @return A {@link ICryptoTransform} implementation + * + * @param key The key material to be used. + * @param iv The initialization vector to be used. + * @param additionalAuthenticatedData The authentication data to be used with authenticating encryption implementation + * (ignored for non-authenticating implementation). + * @param provider The provider to use. + * @return A {@link ICryptoTransform} implementation. */ - abstract ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] authenticationData, Provider provider) + abstract ICryptoTransform createEncryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, + byte[] authenticationTag, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException; /* - * Creates a {@link ICryptoTransform} implementation for decryption - * using the supplied initialization vector and the specific provider for the Java Security API. - * @param key - * The key material to be used. - * @param iv - * The initialization vector to be used. - * @param authenticationData - * The authentication data to be used with authenticating encryption implementation (ignored for - * non-authenticating implementation) - * @param authenticationTag - * The authentication tag to verify when using authenticating encryption implementation (ignored for - * non-authenticating implementation) - * @return A {@link ICryptoTransform} implementation + * Creates a {@link ICryptoTransform} implementation for decryption using the supplied initialization vector and the + * specific provider for the Java Security API. + * + * @param key The key material to be used. + * @param iv The initialization vector to be used. + * @param additionalAuthenticatedData The authentication data to be used with authenticating encryption implementation + * (ignored for non-authenticating implementation). + * @param authenticationTag The authentication tag to verify when using authenticating encryption implementation + * (ignored for non-authenticating implementation). + * @return A {@link ICryptoTransform} implementation. */ - abstract ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] authenticationData, + abstract ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, byte[] authenticationTag) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException; /* - * Creates a {@link ICryptoTransform} implementation for decryption - * using the supplied initialization vector and the specific provider for the Java Security API. - * @param key - * The key material to be used. - * @param iv - * The initialization vector to be used. - * @param authenticationData - * The authentication data to be used with authenticating encryption implementation (ignored for - * non-authenticating implementation) - * @param authenticationTag - * The authentication tag to verify when using authenticating encryption implementation (ignored for - * non-authenticating implementation) - * @param provider - * The provider to use. + * Creates a {@link ICryptoTransform} implementation for decryption using the supplied initialization vector and the + * specific provider for the Java Security API. + * + * @param key The key material to be used. + * @param iv The initialization vector to be used. + * @param additionalAuthenticatedData The authentication data to be used with authenticating encryption implementation + * (ignored for non-authenticating implementation). + * @param authenticationTag The authentication tag to verify when using authenticating encryption implementation + * (ignored for non-authenticating implementation). + * @param provider The provider to use. * @return A {@link ICryptoTransform} implementation */ - abstract ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] authenticationData, + abstract ICryptoTransform createDecryptor(byte[] key, byte[] iv, byte[] additionalAuthenticatedData, byte[] authenticationTag, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException; - } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/SymmetricKeyCryptographyClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/SymmetricKeyCryptographyClient.java index 8f01438692608..f253e52f8a23b 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/SymmetricKeyCryptographyClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/SymmetricKeyCryptographyClient.java @@ -18,16 +18,20 @@ import reactor.core.publisher.Mono; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; class SymmetricKeyCryptographyClient extends LocalKeyCryptographyClient { + private static final int CBC_BLOCK_SIZE = 16; + private static final int GCM_NONCE_SIZE = 12; + private final ClientLogger logger = new ClientLogger(SymmetricKeyCryptographyClient.class); private byte[] key; - /* - * Creates a RsaKeyCryptographyClient that uses {@code serviceClient) to service requests + /** + * Creates a {@link SymmetricKeyCryptographyClient} to perform local cryptography operations. * - * @param key the key pair to use for cryptography operations. + * @param serviceClient The client to route the requests through. */ SymmetricKeyCryptographyClient(CryptographyServiceClient serviceClient) { super(serviceClient); @@ -46,14 +50,113 @@ private byte[] getKey(JsonWebKey key) { } @Override - Mono encryptAsync(EncryptionAlgorithm algorithm, byte[] plaintext, Context context, JsonWebKey jsonWebKey) { - return Mono.error(new UnsupportedOperationException("encrypt operation not supported for AES/OCT/Symmetric key")); + Mono encryptAsync(EncryptOptions encryptOptions, Context context, JsonWebKey jsonWebKey) { + this.key = getKey(jsonWebKey); + + if (key == null || key.length == 0) { + throw logger.logExceptionAsError(new IllegalArgumentException("Key is empty.")); + } + + // Interpret the algorithm + EncryptionAlgorithm algorithm = encryptOptions.getAlgorithm(); + Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm.toString()); + + if (!(baseAlgorithm instanceof SymmetricEncryptionAlgorithm)) { + return Mono.error(new NoSuchAlgorithmException(algorithm.toString())); + } + + SymmetricEncryptionAlgorithm symmetricEncryptionAlgorithm = (SymmetricEncryptionAlgorithm) baseAlgorithm; + + ICryptoTransform transform; + + byte[] iv = encryptOptions.getIv(); + byte[] additionalAuthenticatedData = encryptOptions.getAdditionalAuthenticatedData(); + byte[] authenticationTag = generateRandomByteArray(GCM_NONCE_SIZE); + + if (iv == null) { + if (algorithm == EncryptionAlgorithm.A128GCM || algorithm == EncryptionAlgorithm.A192GCM + || algorithm == EncryptionAlgorithm.A256GCM) { + + iv = generateRandomByteArray(GCM_NONCE_SIZE); + } else if (algorithm == EncryptionAlgorithm.A128CBC || algorithm == EncryptionAlgorithm.A192CBC + || algorithm == EncryptionAlgorithm.A256CBC || algorithm == EncryptionAlgorithm.A128CBCPAD + || algorithm == EncryptionAlgorithm.A192CBCPAD || algorithm == EncryptionAlgorithm.A256CBCPAD) { + + iv = generateRandomByteArray(CBC_BLOCK_SIZE); + } + } + + try { + transform = symmetricEncryptionAlgorithm.createEncryptor(this.key, iv, additionalAuthenticatedData, + authenticationTag); + } catch (Exception e) { + return Mono.error(e); + } + + byte[] encrypted; + + try { + encrypted = transform.doFinal(encryptOptions.getPlaintext()); + } catch (Exception e) { + return Mono.error(e); + } + + return Mono.just(new EncryptResult(encrypted, algorithm, jsonWebKey.getId(), iv, additionalAuthenticatedData, + authenticationTag)); } @Override - Mono decryptAsync(EncryptionAlgorithm algorithm, byte[] cipherText, Context context, - JsonWebKey jsonWebKey) { - return Mono.error(new UnsupportedOperationException("decrypt operation not supported for AES/OCT/Symmetric key")); + Mono decryptAsync(DecryptOptions decryptOptions, Context context, JsonWebKey jsonWebKey) { + this.key = getKey(jsonWebKey); + + if (key == null || key.length == 0) { + throw logger.logExceptionAsError(new IllegalArgumentException("Key is empty.")); + } + + // Interpret the algorithm + EncryptionAlgorithm algorithm = decryptOptions.getAlgorithm(); + Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm.toString()); + + if (!(baseAlgorithm instanceof SymmetricEncryptionAlgorithm)) { + return Mono.error(new NoSuchAlgorithmException(algorithm.toString())); + } + + SymmetricEncryptionAlgorithm symmetricEncryptionAlgorithm = (SymmetricEncryptionAlgorithm) baseAlgorithm; + + ICryptoTransform transform; + + byte[] iv = decryptOptions.getIv(); + byte[] additionalAuthenticatedData = decryptOptions.getAdditionalAuthenticatedData(); + byte[] authenticationTag = decryptOptions.getAuthenticationTag(); + + if (iv == null) { + if (algorithm == EncryptionAlgorithm.A128GCM || algorithm == EncryptionAlgorithm.A192GCM + || algorithm == EncryptionAlgorithm.A256GCM) { + + iv = generateRandomByteArray(GCM_NONCE_SIZE); + } else if (algorithm == EncryptionAlgorithm.A128CBC || algorithm == EncryptionAlgorithm.A192CBC + || algorithm == EncryptionAlgorithm.A256CBC || algorithm == EncryptionAlgorithm.A128CBCPAD + || algorithm == EncryptionAlgorithm.A192CBCPAD || algorithm == EncryptionAlgorithm.A256CBCPAD) { + + iv = generateRandomByteArray(CBC_BLOCK_SIZE); + } + } + + try { + transform = symmetricEncryptionAlgorithm.createDecryptor(this.key, iv, additionalAuthenticatedData, authenticationTag); + } catch (Exception e) { + return Mono.error(e); + } + + byte[] decrypted; + + try { + decrypted = transform.doFinal(decryptOptions.getCiphertext()); + } catch (Exception e) { + return Mono.error(e); + } + + return Mono.just(new DecryptResult(decrypted, algorithm, jsonWebKey.getId())); } @Override @@ -69,7 +172,6 @@ Mono verifyAsync(SignatureAlgorithm algorithm, byte[] digest, byte @Override Mono wrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] key, Context context, JsonWebKey jsonWebKey) { - this.key = getKey(jsonWebKey); if (key == null || key.length == 0) { @@ -79,21 +181,21 @@ Mono wrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] key, Context co // Interpret the algorithm Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm.toString()); - if (baseAlgorithm == null || !(baseAlgorithm instanceof LocalKeyWrapAlgorithm)) { + if (!(baseAlgorithm instanceof LocalKeyWrapAlgorithm)) { return Mono.error(new NoSuchAlgorithmException(algorithm.toString())); } - LocalKeyWrapAlgorithm algo = (LocalKeyWrapAlgorithm) baseAlgorithm; + LocalKeyWrapAlgorithm localKeyWrapAlgorithm = (LocalKeyWrapAlgorithm) baseAlgorithm; - ICryptoTransform transform = null; + ICryptoTransform transform; try { - transform = algo.createEncryptor(this.key, null, null); + transform = localKeyWrapAlgorithm.createEncryptor(this.key, null, null); } catch (Exception e) { return Mono.error(e); } - byte[] encrypted = null; + byte[] encrypted; try { encrypted = transform.doFinal(key); @@ -105,22 +207,21 @@ Mono wrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] key, Context co } @Override - Mono unwrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] encryptedKey, Context context, - JsonWebKey jsonWebKey) { - key = getKey(jsonWebKey); + Mono unwrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] encryptedKey, Context context, JsonWebKey jsonWebKey) { + this.key = getKey(jsonWebKey); Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm.toString()); - if (baseAlgorithm == null || !(baseAlgorithm instanceof LocalKeyWrapAlgorithm)) { + if (!(baseAlgorithm instanceof LocalKeyWrapAlgorithm)) { return Mono.error(new NoSuchAlgorithmException(algorithm.toString())); } - LocalKeyWrapAlgorithm algo = (LocalKeyWrapAlgorithm) baseAlgorithm; + LocalKeyWrapAlgorithm localKeyWrapAlgorithm = (LocalKeyWrapAlgorithm) baseAlgorithm; ICryptoTransform transform; try { - transform = algo.createDecryptor(key, null, null); + transform = localKeyWrapAlgorithm.createDecryptor(this.key, null, null); } catch (Exception e) { return Mono.error(e); } @@ -146,4 +247,19 @@ Mono verifyDataAsync(SignatureAlgorithm algorithm, byte[] data, by JsonWebKey key) { return verifyAsync(algorithm, data, signature, context, key); } + + private byte[] generateRandomByteArray(int sizeInBytes) { + byte[] iv = new byte[0]; + SecureRandom randomSecureRandom; + + try { + randomSecureRandom = SecureRandom.getInstance("SHA1PRNG"); + iv = new byte[sizeInBytes]; + randomSecureRandom.nextBytes(iv); + } catch (NoSuchAlgorithmException e) { + logger.logThrowableAsError(e); + } + + return iv; + } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/models/EncryptResult.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/models/EncryptResult.java index 2ac529a70bfeb..bce3f6e444d8b 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/models/EncryptResult.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/models/EncryptResult.java @@ -26,6 +26,22 @@ public final class EncryptResult { */ private final String keyId; + /** + * Initialization vector for symmetric algorithms. + */ + private final byte[] iv; + + /** + * Additional data to authenticate but not encrypt/decrypt when using authenticated crypto algorithms. + */ + private final byte[] additionalAuthenticatedData; + + /** + * The tag to authenticate when performing decryption with an authenticated algorithm. + */ + private final byte[] authenticationTag; + + /** * Creates the instance of Encrypt Result holding encryption operation response information. * @param cipherText The encrypted content. @@ -33,9 +49,26 @@ public final class EncryptResult { * @param keyId The identifier of the key usd for the encryption operation. */ public EncryptResult(byte[] cipherText, EncryptionAlgorithm algorithm, String keyId) { + this(cipherText, algorithm, keyId, null, null, null); + } + + /** + * Creates the instance of Encrypt Result holding encryption operation response information. + * @param cipherText The encrypted content. + * @param algorithm The algorithm used to encrypt the content. + * @param keyId The identifier of the key usd for the encryption operation. + * @param iv Initialization vector for symmetric algorithms. + * @param additionalAuthenticatedData Additional data to authenticate but not encrypt/decrypt when using authenticated crypto algorithms. + * @param authenticationTag The tag to authenticate when performing decryption with an authenticated algorithm. + */ + public EncryptResult(byte[] cipherText, EncryptionAlgorithm algorithm, String keyId, byte[] iv, + byte[] additionalAuthenticatedData, byte[] authenticationTag) { this.cipherText = CoreUtils.clone(cipherText); this.algorithm = algorithm; this.keyId = keyId; + this.iv = CoreUtils.clone(iv); + this.additionalAuthenticatedData = CoreUtils.clone(additionalAuthenticatedData); + this.authenticationTag = CoreUtils.clone(authenticationTag); } /** @@ -61,4 +94,31 @@ public byte[] getCipherText() { public EncryptionAlgorithm getAlgorithm() { return algorithm; } + + /** + * Get the initialization vector used by symmetric algorithms. + * + * @return The initialization vector. + */ + public byte[] getIv() { + return CoreUtils.clone(iv); + } + + /** + * Get additional data to authenticate the encrypted content. + * + * @return The additional authenticated data. + */ + public byte[] getAdditionalAuthenticatedData() { + return CoreUtils.clone(additionalAuthenticatedData); + } + + /** + * Get the tag to authenticate the encrypted content. + * + * @return The authentication tag. + */ + public byte[] getAuthenticationTag() { + return CoreUtils.clone(authenticationTag); + } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/models/EncryptionAlgorithm.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/models/EncryptionAlgorithm.java index c59f1b0d3e53c..ba21cb8ce3f57 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/models/EncryptionAlgorithm.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/cryptography/models/EncryptionAlgorithm.java @@ -27,11 +27,36 @@ public final class EncryptionAlgorithm extends ExpandableStringEnum System.out.printf("Received encrypted content of length %d with algorithm %s \n", encryptResult.getCipherText().length, encryptResult.getAlgorithm().toString())); // END: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.encrypt#EncryptionAlgorithm-byte + + // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.encrypt#EncryptOptions + byte[] plainTextBytes = new byte[100]; + + new Random(0x1234567L).nextBytes(plainTextBytes); + + byte[] iv = { + (byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, + (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04 + }; + EncryptOptions encryptOptions = EncryptOptions.createAes128CbcOptions(plainTextBytes, iv); + + cryptographyAsyncClient.encrypt(encryptOptions) + .subscriberContext(reactor.util.context.Context.of(key1, value1, key2, value2)) + .subscribe(encryptResult -> + System.out.printf("Received encrypted content of length %d with algorithm %s \n", + encryptResult.getCipherText().length, encryptResult.getAlgorithm().toString())); + // END: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.encrypt#EncryptOptions } /** - * Generates a code sample for using {@link CryptographyAsyncClient#decrypt(EncryptionAlgorithm, byte[])} and - * {@link CryptographyAsyncClient#decrypt(EncryptionAlgorithm, byte[])} + * Generates code samples for using {@link CryptographyAsyncClient#decrypt(EncryptionAlgorithm, byte[])} and + * {@link CryptographyAsyncClient#decrypt(DecryptOptions)}. */ public void decrypt() { CryptographyAsyncClient cryptographyAsyncClient = createAsyncClient(); + // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.decrypt#EncryptionAlgorithm-byte - byte[] plainText = new byte[100]; - new Random(0x1234567L).nextBytes(plainText); - cryptographyAsyncClient.decrypt(EncryptionAlgorithm.RSA_OAEP, plainText) + byte[] cipherText = new byte[100]; + + new Random(0x1234567L).nextBytes(cipherText); + + cryptographyAsyncClient.decrypt(EncryptionAlgorithm.RSA_OAEP, cipherText) .subscriberContext(reactor.util.context.Context.of(key1, value1, key2, value2)) .subscribe(decryptResult -> System.out.printf("Received decrypted content of length %d\n", decryptResult.getPlainText().length)); // END: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.decrypt#EncryptionAlgorithm-byte + + // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.decrypt#DecryptOptions + byte[] cipherTextBytes = new byte[100]; + + new Random(0x1234567L).nextBytes(cipherTextBytes); + + byte[] iv = { + (byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, + (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04 + }; + DecryptOptions decryptOptions = DecryptOptions.createAes128CbcOptions(cipherTextBytes, iv); + + cryptographyAsyncClient.decrypt(decryptOptions) + .subscriberContext(reactor.util.context.Context.of(key1, value1, key2, value2)) + .subscribe(decryptResult -> + System.out.printf("Received decrypted content of length %d\n", decryptResult.getPlainText().length)); + // END: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.decrypt#DecryptOptions } /** @@ -186,6 +220,7 @@ public void signDataVerifyData() throws NoSuchAlgorithmException { // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.signData#SignatureAlgorithm-byte byte[] data = new byte[100]; new Random(0x1234567L).nextBytes(data); + cryptographyAsyncClient.sign(SignatureAlgorithm.ES256, data) .subscriberContext(reactor.util.context.Context.of(key1, value1, key2, value2)) .subscribe(signResult -> @@ -202,14 +237,14 @@ public void signDataVerifyData() throws NoSuchAlgorithmException { /** * Generates a code sample for using {@link CryptographyAsyncClient#wrapKey(KeyWrapAlgorithm, byte[])} and - * {@link CryptographyAsyncClient#unwrapKey(KeyWrapAlgorithm, byte[])} + * {@link CryptographyAsyncClient#unwrapKey(KeyWrapAlgorithm, byte[])}. */ public void wrapKeyUnwrapKey() { CryptographyAsyncClient cryptographyAsyncClient = createAsyncClient(); - byte[] encryptedKey = new byte[100]; // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.wrapKey#KeyWrapAlgorithm-byte byte[] key = new byte[100]; new Random(0x1234567L).nextBytes(key); + cryptographyAsyncClient.wrapKey(KeyWrapAlgorithm.RSA_OAEP, key) .subscriberContext(reactor.util.context.Context.of(key1, value1, key2, value2)) .subscribe(keyWrapResult -> @@ -218,7 +253,10 @@ public void wrapKeyUnwrapKey() { // END: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.wrapKey#KeyWrapAlgorithm-byte // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient.unwrapKey#KeyWrapAlgorithm-byte - cryptographyAsyncClient.unwrapKey(KeyWrapAlgorithm.RSA_OAEP, encryptedKey) + byte[] wrappedKey = new byte[100]; + new Random(0x1234567L).nextBytes(key); + + cryptographyAsyncClient.unwrapKey(KeyWrapAlgorithm.RSA_OAEP, wrappedKey) .subscriberContext(reactor.util.context.Context.of(key1, value1, key2, value2)) .subscribe(keyUnwrapResult -> System.out.printf("Received key of length %d", keyUnwrapResult.getKey().length)); diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientJavaDocCodeSnippets.java b/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientJavaDocCodeSnippets.java index 757975b6aba6b..533907acf8b30 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientJavaDocCodeSnippets.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientJavaDocCodeSnippets.java @@ -69,52 +69,96 @@ public void getKeySnippets() { } /** - * Generates a code sample for using {@link CryptographyClient#encrypt(EncryptionAlgorithm, byte[])} and - * {@link CryptographyClient#encrypt(EncryptionAlgorithm, byte[])} + * Generates a code sample for using {@link CryptographyClient#encrypt(EncryptionAlgorithm, byte[])}, + * {@link CryptographyClient#encrypt(EncryptionAlgorithm, byte[], Context)} and + * {@link CryptographyClient#encrypt(EncryptOptions, Context)}. */ public void encrypt() { CryptographyClient cryptographyClient = createClient(); - byte[] iv = {(byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04}; - byte[] authData = { - (byte) 0x54, (byte) 0x68, (byte) 0x65, (byte) 0x20, (byte) 0x73, (byte) 0x65, (byte) 0x63, (byte) 0x6f, (byte) 0x6e, (byte) 0x64, (byte) 0x20, (byte) 0x70, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x63, - (byte) 0x69, (byte) 0x70, (byte) 0x6c, (byte) 0x65, (byte) 0x20, (byte) 0x6f, (byte) 0x66, (byte) 0x20, (byte) 0x41, (byte) 0x75, (byte) 0x67, (byte) 0x75, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x20, - (byte) 0x4b, (byte) 0x65, (byte) 0x72, (byte) 0x63, (byte) 0x6b, (byte) 0x68, (byte) 0x6f, (byte) 0x66, (byte) 0x66, (byte) 0x73 - }; + // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyClient.encrypt#EncryptionAlgorithm-byte byte[] plainText = new byte[100]; + new Random(0x1234567L).nextBytes(plainText); + EncryptResult encryptResult = cryptographyClient.encrypt(EncryptionAlgorithm.RSA_OAEP, plainText); + System.out.printf("Received encrypted content of length %d with algorithm %s \n", encryptResult.getCipherText().length, encryptResult.getAlgorithm().toString()); // END: com.azure.security.keyvault.keys.cryptography.CryptographyClient.encrypt#EncryptionAlgorithm-byte // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyClient.encrypt#EncryptionAlgorithm-byte-Context byte[] plainTextToEncrypt = new byte[100]; + new Random(0x1234567L).nextBytes(plainTextToEncrypt); + EncryptResult encryptionResult = cryptographyClient.encrypt(EncryptionAlgorithm.RSA_OAEP, plainTextToEncrypt, new Context(key1, value1)); + System.out.printf("Received encrypted content of length %d with algorithm %s \n", encryptionResult.getCipherText().length, encryptionResult.getAlgorithm().toString()); // END: com.azure.security.keyvault.keys.cryptography.CryptographyClient.encrypt#EncryptionAlgorithm-byte-Context + + // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyClient.encrypt#EncryptOptions-Context + byte[] myPlainText = new byte[100]; + + new Random(0x1234567L).nextBytes(myPlainText); + + byte[] iv = { + (byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, + (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04 + }; + EncryptOptions encryptOptions = EncryptOptions.createAes128CbcOptions(myPlainText, iv); + EncryptResult encryptedResult = cryptographyClient.encrypt(encryptOptions, new Context(key1, value1)); + + System.out.printf("Received encrypted content of length %d with algorithm %s \n", + encryptedResult.getCipherText().length, encryptedResult.getAlgorithm().toString()); + // END: com.azure.security.keyvault.keys.cryptography.CryptographyClient.encrypt#EncryptOptions-Context } /** - * Generates a code sample for using {@link CryptographyClient#decrypt(EncryptionAlgorithm, byte[])} and - * {@link CryptographyClient#decrypt(EncryptionAlgorithm, byte[])} + * Generates a code sample for using {@link CryptographyClient#decrypt(EncryptionAlgorithm, byte[])}, + * {@link CryptographyClient#decrypt(EncryptionAlgorithm, byte[], Context)} and + * {@link CryptographyClient#decrypt(DecryptOptions, Context)}. */ public void decrypt() { CryptographyClient cryptographyClient = createClient(); - byte[] encryptedData = new byte[100]; + // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyClient.decrypt#EncryptionAlgorithm-byte - DecryptResult decryptResult = cryptographyClient.decrypt(EncryptionAlgorithm.RSA_OAEP, encryptedData); + byte[] cipherText = new byte[100]; + + new Random(0x1234567L).nextBytes(cipherText); + + DecryptResult decryptResult = cryptographyClient.decrypt(EncryptionAlgorithm.RSA_OAEP, cipherText); + System.out.printf("Received decrypted content of length %d\n", decryptResult.getPlainText().length); // END: com.azure.security.keyvault.keys.cryptography.CryptographyClient.decrypt#EncryptionAlgorithm-byte // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyClient.decrypt#EncryptionAlgorithm-byte-Context - DecryptResult decryptionResult = cryptographyClient.decrypt(EncryptionAlgorithm.RSA_OAEP, encryptedData, + byte[] cipherTextToDecrypt = new byte[100]; + + new Random(0x1234567L).nextBytes(cipherTextToDecrypt); + + DecryptResult decryptionResult = cryptographyClient.decrypt(EncryptionAlgorithm.RSA_OAEP, cipherTextToDecrypt, new Context(key1, value1)); + System.out.printf("Received decrypted content of length %d\n", decryptionResult.getPlainText().length); // END: com.azure.security.keyvault.keys.cryptography.CryptographyClient.decrypt#EncryptionAlgorithm-byte-Context + + // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyClient.decrypt#DecryptOptions-Context + byte[] myCipherText = new byte[100]; + + new Random(0x1234567L).nextBytes(myCipherText); + + byte[] iv = { + (byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, + (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04 + }; + DecryptOptions decryptOptions = DecryptOptions.createAes128CbcOptions(myCipherText, iv); + DecryptResult decryptedResult = cryptographyClient.decrypt(decryptOptions, new Context(key1, value1)); + + System.out.printf("Received decrypted content of length %d\n", decryptedResult.getPlainText().length); + // END: com.azure.security.keyvault.keys.cryptography.CryptographyClient.decrypt#DecryptOptions-Context } /** @@ -196,36 +240,55 @@ public void signDataVerifyData() throws NoSuchAlgorithmException { } /** - * Generates a code sample for using {@link CryptographyClient#wrapKey(KeyWrapAlgorithm, byte[])} and - * {@link CryptographyClient#unwrapKey(KeyWrapAlgorithm, byte[])} + * Generates a code sample for using {@link CryptographyClient#wrapKey(KeyWrapAlgorithm, byte[])}, + * {@link CryptographyClient#wrapKey(KeyWrapAlgorithm, byte[], Context)}, + * {@link CryptographyClient#unwrapKey(KeyWrapAlgorithm, byte[])} and + * {@link CryptographyClient#unwrapKey(KeyWrapAlgorithm, byte[], Context)}. */ public void wrapKeyUnwrapKey() { CryptographyClient cryptographyClient = createClient(); - byte[] encryptedKey = new byte[100]; + // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyClient.wrapKey#KeyWrapAlgorithm-byte byte[] key = new byte[100]; + new Random(0x1234567L).nextBytes(key); + WrapResult wrapResult = cryptographyClient.wrapKey(KeyWrapAlgorithm.RSA_OAEP, key); + System.out.printf("Received encypted key of length %d with algorithm %s", wrapResult.getEncryptedKey().length, wrapResult.getAlgorithm().toString()); // END: com.azure.security.keyvault.keys.cryptography.CryptographyClient.wrapKey#KeyWrapAlgorithm-byte // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyClient.wrapKey#KeyWrapAlgorithm-byte-Context byte[] keyContent = new byte[100]; + new Random(0x1234567L).nextBytes(keyContent); - WrapResult keyWrapResponse = cryptographyClient.wrapKey(KeyWrapAlgorithm.RSA_OAEP, keyContent); - System.out.printf("Received encypted key of length %d with algorithm %s", keyWrapResponse.getEncryptedKey().length, - keyWrapResponse.getAlgorithm().toString(), new Context(key1, value1)); + + WrapResult keyWrapResponse = cryptographyClient.wrapKey(KeyWrapAlgorithm.RSA_OAEP, keyContent, + new Context(key1, value1)); + + System.out.printf("Received encrypted key of length %d with algorithm %s", keyWrapResponse.getEncryptedKey().length, + keyWrapResponse.getAlgorithm().toString()); // END: com.azure.security.keyvault.keys.cryptography.CryptographyClient.wrapKey#KeyWrapAlgorithm-byte-Context // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyClient.unwrapKey#KeyWrapAlgorithm-byte - UnwrapResult unwrapResult = cryptographyClient.unwrapKey(KeyWrapAlgorithm.RSA_OAEP, encryptedKey); + byte[] wrappedKey = new byte[100]; + + new Random(0x1234567L).nextBytes(wrappedKey); + + UnwrapResult unwrapResult = cryptographyClient.unwrapKey(KeyWrapAlgorithm.RSA_OAEP, wrappedKey); + System.out.printf("Received key of length %d", unwrapResult.getKey().length); // END: com.azure.security.keyvault.keys.cryptography.CryptographyClient.unwrapKey#KeyWrapAlgorithm-byte // BEGIN: com.azure.security.keyvault.keys.cryptography.CryptographyClient.unwrapKey#KeyWrapAlgorithm-byte-Context - UnwrapResult keyUnwrapResponse = cryptographyClient.unwrapKey(KeyWrapAlgorithm.RSA_OAEP, encryptedKey, + byte[] wrappedKeyContent = new byte[100]; + + new Random(0x1234567L).nextBytes(wrappedKeyContent); + + UnwrapResult keyUnwrapResponse = cryptographyClient.unwrapKey(KeyWrapAlgorithm.RSA_OAEP, wrappedKeyContent, new Context(key2, value2)); + System.out.printf("Received key of length %d", keyUnwrapResponse.getKey().length); // END: com.azure.security.keyvault.keys.cryptography.CryptographyClient.unwrapKey#KeyWrapAlgorithm-byte-Context } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyAsyncClientJavaDocCodeSnippets.java b/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyAsyncClientJavaDocCodeSnippets.java index 98fc655fc8fcf..271c35b0b3a33 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyAsyncClientJavaDocCodeSnippets.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyAsyncClientJavaDocCodeSnippets.java @@ -44,12 +44,7 @@ public LocalCryptographyAsyncClient createAsyncClient() { */ public void encrypt() { LocalCryptographyAsyncClient cryptographyAsyncClient = createAsyncClient(); - byte[] iv = {(byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04}; - byte[] authData = { - (byte) 0x54, (byte) 0x68, (byte) 0x65, (byte) 0x20, (byte) 0x73, (byte) 0x65, (byte) 0x63, (byte) 0x6f, (byte) 0x6e, (byte) 0x64, (byte) 0x20, (byte) 0x70, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x63, - (byte) 0x69, (byte) 0x70, (byte) 0x6c, (byte) 0x65, (byte) 0x20, (byte) 0x6f, (byte) 0x66, (byte) 0x20, (byte) 0x41, (byte) 0x75, (byte) 0x67, (byte) 0x75, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x20, - (byte) 0x4b, (byte) 0x65, (byte) 0x72, (byte) 0x63, (byte) 0x6b, (byte) 0x68, (byte) 0x6f, (byte) 0x66, (byte) 0x66, (byte) 0x73 - }; + // BEGIN: com.azure.security.keyvault.keys.cryptography.LocalCryptographyAsyncClient.encrypt#EncryptionAlgorithm-byte byte[] plainText = new byte[100]; new Random(0x1234567L).nextBytes(plainText); @@ -59,6 +54,22 @@ public void encrypt() { System.out.printf("Received encrypted content of length %d with algorithm %s \n", encryptResult.getCipherText().length, encryptResult.getAlgorithm().toString())); // END: com.azure.security.keyvault.keys.cryptography.LocalCryptographyAsyncClient.encrypt#EncryptionAlgorithm-byte + + // BEGIN: com.azure.security.keyvault.keys.cryptography.LocalCryptographyAsyncClient.encrypt#EncryptOptions + byte[] plainTextBytes = new byte[100]; + new Random(0x1234567L).nextBytes(plainTextBytes); + byte[] iv = { + (byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, + (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04 + }; + EncryptOptions encryptOptions = EncryptOptions.createAes128CbcOptions(plainTextBytes, iv); + + cryptographyAsyncClient.encrypt(encryptOptions) + .subscriberContext(reactor.util.context.Context.of(key1, value1, key2, value2)) + .subscribe(encryptResult -> + System.out.printf("Received encrypted content of length %d with algorithm %s \n", + encryptResult.getCipherText().length, encryptResult.getAlgorithm().toString())); + // END: com.azure.security.keyvault.keys.cryptography.LocalCryptographyAsyncClient.encrypt#EncryptOptions } /** @@ -75,6 +86,21 @@ public void decrypt() { .subscribe(decryptResult -> System.out.printf("Received decrypted content of length %d\n", decryptResult.getPlainText().length)); // END: com.azure.security.keyvault.keys.cryptography.LocalCryptographyAsyncClient.decrypt#EncryptionAlgorithm-byte + + // BEGIN: com.azure.security.keyvault.keys.cryptography.LocalCryptographyAsyncClient.decrypt#DecryptOptions + byte[] plainTextBytes = new byte[100]; + new Random(0x1234567L).nextBytes(plainTextBytes); + byte[] iv = { + (byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, + (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04 + }; + DecryptOptions decryptOptions = DecryptOptions.createAes128CbcOptions(plainTextBytes, iv); + + cryptographyAsyncClient.decrypt(decryptOptions) + .subscriberContext(reactor.util.context.Context.of(key1, value1, key2, value2)) + .subscribe(decryptResult -> + System.out.printf("Received decrypted content of length %d\n", decryptResult.getPlainText().length)); + // END: com.azure.security.keyvault.keys.cryptography.LocalCryptographyAsyncClient.decrypt#DecryptOptions } /** diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientJavaDocCodeSnippets.java b/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientJavaDocCodeSnippets.java index e730fa87ee0ab..6cefc6c630743 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientJavaDocCodeSnippets.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientJavaDocCodeSnippets.java @@ -49,12 +49,7 @@ public LocalCryptographyClient createClient() { */ public void encrypt() { LocalCryptographyClient cryptographyClient = createClient(); - byte[] iv = {(byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04}; - byte[] authData = { - (byte) 0x54, (byte) 0x68, (byte) 0x65, (byte) 0x20, (byte) 0x73, (byte) 0x65, (byte) 0x63, (byte) 0x6f, (byte) 0x6e, (byte) 0x64, (byte) 0x20, (byte) 0x70, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x63, - (byte) 0x69, (byte) 0x70, (byte) 0x6c, (byte) 0x65, (byte) 0x20, (byte) 0x6f, (byte) 0x66, (byte) 0x20, (byte) 0x41, (byte) 0x75, (byte) 0x67, (byte) 0x75, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x20, - (byte) 0x4b, (byte) 0x65, (byte) 0x72, (byte) 0x63, (byte) 0x6b, (byte) 0x68, (byte) 0x6f, (byte) 0x66, (byte) 0x66, (byte) 0x73 - }; + // BEGIN: com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.encrypt#EncryptionAlgorithm-byte byte[] plainText = new byte[100]; new Random(0x1234567L).nextBytes(plainText); @@ -62,6 +57,20 @@ public void encrypt() { System.out.printf("Received encrypted content of length %d with algorithm %s \n", encryptResult.getCipherText().length, encryptResult.getAlgorithm().toString()); // END: com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.encrypt#EncryptionAlgorithm-byte + + // BEGIN: com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.encrypt#EncryptOptions + byte[] plainTextBytes = new byte[100]; + new Random(0x1234567L).nextBytes(plainTextBytes); + byte[] iv = { + (byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, + (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04 + }; + EncryptOptions encryptOptions = EncryptOptions.createAes128CbcOptions(plainTextBytes, iv); + EncryptResult encryptedResult = cryptographyClient.encrypt(encryptOptions); + + System.out.printf("Received encrypted content of length %d with algorithm %s \n", + encryptedResult.getCipherText().length, encryptedResult.getAlgorithm().toString()); + // END: com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.encrypt#EncryptOptions } /** @@ -70,11 +79,25 @@ public void encrypt() { */ public void decrypt() { LocalCryptographyClient cryptographyClient = createClient(); - byte[] encryptedData = new byte[100]; + // BEGIN: com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.decrypt#EncryptionAlgorithm-byte + byte[] encryptedData = new byte[100]; DecryptResult decryptResult = cryptographyClient.decrypt(EncryptionAlgorithm.RSA_OAEP, encryptedData); + System.out.printf("Received decrypted content of length %d\n", decryptResult.getPlainText().length); // END: com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.decrypt#EncryptionAlgorithm-byte + + // BEGIN: com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.decrypt#DecryptOptions + byte[] encryptedBytes = new byte[100]; + byte[] iv = { + (byte) 0x1a, (byte) 0xf3, (byte) 0x8c, (byte) 0x2d, (byte) 0xc2, (byte) 0xb9, (byte) 0x6f, (byte) 0xfd, + (byte) 0xd8, (byte) 0x66, (byte) 0x94, (byte) 0x09, (byte) 0x23, (byte) 0x41, (byte) 0xbc, (byte) 0x04 + }; + DecryptOptions decryptOptions = DecryptOptions.createAes128CbcOptions(encryptedBytes, iv); + DecryptResult decryptedResult = cryptographyClient.decrypt(decryptOptions); + + System.out.printf("Received decrypted content of length %d\n", decryptedResult.getPlainText().length); + // END: com.azure.security.keyvault.keys.cryptography.LocalCryptographyClient.decrypt#DecryptOptions } /** diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientTest.java b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientTest.java index 132438756ce30..216db63a4cac9 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientTest.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientTest.java @@ -16,9 +16,19 @@ import com.azure.security.keyvault.keys.models.JsonWebKey; import com.azure.security.keyvault.keys.models.KeyCurveName; -import java.security.*; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; import java.security.spec.ECGenParameterSpec; -import java.util.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -71,11 +81,13 @@ public void encryptDecryptRsa(HttpClient httpClient, CryptographyServiceVersion byte[] plainText = new byte[100]; new Random(0x1234567L).nextBytes(plainText); byte[] cipherText = cryptoClient.encrypt(algorithm, plainText).getCipherText(); - byte[] decryptedText = serviceClient.decrypt(algorithm, cipherText, Context.NONE).block().getPlainText(); + byte[] decryptedText = serviceClient.decrypt(new DecryptOptions(algorithm, cipherText, null, null, + null), Context.NONE).block().getPlainText(); assertArrayEquals(decryptedText, plainText); - cipherText = serviceClient.encrypt(algorithm, plainText, Context.NONE).block().getCipherText(); + cipherText = serviceClient.encrypt(new EncryptOptions(algorithm, plainText, null, null), Context.NONE) + .block().getCipherText(); decryptedText = cryptoClient.decrypt(algorithm, cipherText).getPlainText(); assertArrayEquals(decryptedText, plainText); @@ -101,11 +113,13 @@ public void wrapUnwraptRsa(HttpClient httpClient, CryptographyServiceVersion ser byte[] plainText = new byte[100]; new Random(0x1234567L).nextBytes(plainText); byte[] encryptedKey = cryptoClient.wrapKey(algorithm, plainText).getEncryptedKey(); - byte[] decryptedKey = serviceClient.unwrapKey(algorithm, encryptedKey, Context.NONE).block().getKey(); + byte[] decryptedKey = + serviceClient.unwrapKey(algorithm, encryptedKey, Context.NONE).block().getKey(); assertArrayEquals(decryptedKey, plainText); - encryptedKey = serviceClient.wrapKey(algorithm, plainText, Context.NONE).block().getEncryptedKey(); + encryptedKey = + serviceClient.wrapKey(algorithm, plainText, Context.NONE).block().getEncryptedKey(); decryptedKey = cryptoClient.unwrapKey(algorithm, encryptedKey).getKey(); assertArrayEquals(decryptedKey, plainText); diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientTestBase.java b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientTestBase.java index e61f407eb42f9..50947681766c0 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientTestBase.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/CryptographyClientTestBase.java @@ -34,7 +34,12 @@ import java.security.spec.RSAPrivateCrtKeySpec; import java.security.spec.RSAPublicKeySpec; import java.time.Duration; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; import java.util.function.Consumer; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientTest.java b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientTest.java index ed006bb2ca610..a340b7cc55ecd 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientTest.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientTest.java @@ -34,13 +34,6 @@ protected void beforeTest() { beforeTestSetup(); } - - private LocalCryptographyClient initializeCryptographyClient(JsonWebKey key) { - return new LocalCryptographyClientBuilder() - .key(key) - .buildClient(); - } - @Test public void encryptDecryptRsa() throws Exception { encryptDecryptRsaRunner(keyPair -> { @@ -116,6 +109,50 @@ public void signVerifyEc() throws NoSuchAlgorithmException, InvalidAlgorithmPara Boolean verifyStatus = cryptoClient.verifyData(curveToSignature.get(crv), plainText, signature).isValid(); assertTrue(verifyStatus); } + } + @Test + public void encryptDecryptLocalAes128Cbc() throws NoSuchAlgorithmException { + encryptDecryptAesCbc(128, EncryptionAlgorithm.A128CBC); + } + + @Test + public void encryptDecryptLocalAes192Cbc() throws NoSuchAlgorithmException { + encryptDecryptAesCbc(256, EncryptionAlgorithm.A192CBC); + } + + @Test + public void encryptDecryptLocalAes256Cbc() throws NoSuchAlgorithmException { + encryptDecryptAesCbc(256, EncryptionAlgorithm.A256CBC); + } + + @Test + public void encryptDecryptLocalAes128CbcPad() throws NoSuchAlgorithmException { + encryptDecryptAesCbc(128, EncryptionAlgorithm.A128CBCPAD); + } + + @Test + public void encryptDecryptLocalAes192CbcPad() throws NoSuchAlgorithmException { + encryptDecryptAesCbc(192, EncryptionAlgorithm.A192CBCPAD); + } + + @Test + public void encryptDecryptLocalAes256CbcPad() throws NoSuchAlgorithmException { + encryptDecryptAesCbc(256, EncryptionAlgorithm.A256CBCPAD); + } + + @Test + public void encryptDecryptLocalAes128Gcm() throws NoSuchAlgorithmException { + encryptDecryptAesGcm(128, EncryptionAlgorithm.A128GCM); + } + + @Test + public void encryptDecryptLocalAes192Gcm() throws NoSuchAlgorithmException { + encryptDecryptAesGcm(192, EncryptionAlgorithm.A192GCM); + } + + @Test + public void encryptDecryptLocalAes256Gcm() throws NoSuchAlgorithmException { + encryptDecryptAesGcm(256, EncryptionAlgorithm.A256GCM); } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientTestBase.java b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientTestBase.java index 4e0d1158e3b20..35b5c0ad77bcf 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientTestBase.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/cryptography/LocalCryptographyClientTestBase.java @@ -5,8 +5,15 @@ import com.azure.core.exception.HttpResponseException; import com.azure.core.test.TestBase; +import com.azure.security.keyvault.keys.cryptography.models.DecryptResult; +import com.azure.security.keyvault.keys.cryptography.models.EncryptResult; +import com.azure.security.keyvault.keys.cryptography.models.EncryptionAlgorithm; +import com.azure.security.keyvault.keys.models.JsonWebKey; +import com.azure.security.keyvault.keys.models.KeyOperation; import org.junit.jupiter.api.Test; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.KeyFactory; @@ -15,11 +22,14 @@ import java.security.spec.KeySpec; import java.security.spec.RSAPrivateCrtKeySpec; import java.security.spec.RSAPublicKeySpec; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.function.Consumer; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -32,6 +42,12 @@ protected String getTestName() { void beforeTestSetup() { } + static LocalCryptographyClient initializeCryptographyClient(JsonWebKey key) { + return new LocalCryptographyClientBuilder() + .key(key) + .buildClient(); + } + @Test public abstract void encryptDecryptRsa() throws Exception; @@ -41,6 +57,33 @@ void encryptDecryptRsaRunner(Consumer testRunner) throws Exception { testRunner.accept(getWellKnownKey()); } + @Test + public abstract void encryptDecryptLocalAes128Cbc() throws Exception; + + @Test + public abstract void encryptDecryptLocalAes192Cbc() throws Exception; + + @Test + public abstract void encryptDecryptLocalAes256Cbc() throws Exception; + + @Test + public abstract void encryptDecryptLocalAes128CbcPad() throws Exception; + + @Test + public abstract void encryptDecryptLocalAes192CbcPad() throws Exception; + + @Test + public abstract void encryptDecryptLocalAes256CbcPad() throws Exception; + + @Test + public abstract void encryptDecryptLocalAes128Gcm() throws Exception; + + @Test + public abstract void encryptDecryptLocalAes192Gcm() throws Exception; + + @Test + public abstract void encryptDecryptLocalAes256Gcm() throws Exception; + @Test public abstract void signVerifyEc() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException; @@ -65,6 +108,50 @@ private static KeyPair getWellKnownKey() throws Exception { return new KeyPair(keyFactory.generatePublic(publicKeySpec), keyFactory.generatePrivate(privateKeySpec)); } + static void encryptDecryptAesCbc(int keySize, EncryptionAlgorithm algorithm) throws NoSuchAlgorithmException { + byte[] plaintext = "My16BitPlaintext".getBytes(); + byte[] iv = "My16BytesTestIv.".getBytes(); + LocalCryptographyClient localCryptographyClient = initializeCryptographyClient(getTestJsonWebKey(keySize)); + EncryptOptions encryptOptions = new EncryptOptions(algorithm, plaintext, iv, null); + EncryptResult encryptResult = + localCryptographyClient.encrypt(encryptOptions); + DecryptOptions decryptOptions = new DecryptOptions(algorithm, encryptResult.getCipherText(), iv, null, null); + DecryptResult decryptResult = + localCryptographyClient.decrypt(decryptOptions); + + assertArrayEquals(plaintext, decryptResult.getPlainText()); + } + + static void encryptDecryptAesGcm(int keySize, EncryptionAlgorithm algorithm) throws NoSuchAlgorithmException { + byte[] plaintext = "My16BitPlaintext".getBytes(); + byte[] iv = "My12BytesIv.".getBytes(); + LocalCryptographyClient localCryptographyClient = initializeCryptographyClient(getTestJsonWebKey(keySize)); + EncryptOptions encryptOptions = new EncryptOptions(algorithm, plaintext, iv, null); + EncryptResult encryptResult = + localCryptographyClient.encrypt(encryptOptions); + byte[] authenticationTag = encryptResult.getAuthenticationTag(); + DecryptOptions decryptOptions = new DecryptOptions(algorithm, encryptResult.getCipherText(), iv, + authenticationTag, null); + DecryptResult decryptResult = + localCryptographyClient.decrypt(decryptOptions); + + assertArrayEquals(plaintext, decryptResult.getPlainText()); + } + + private static JsonWebKey getTestJsonWebKey(int keySize) throws NoSuchAlgorithmException { + KeyGenerator keyGen = KeyGenerator.getInstance("AES"); + + keyGen.init(keySize); + + SecretKey secretKey = keyGen.generateKey(); + + List keyOperations = new ArrayList<>(); + keyOperations.add(KeyOperation.ENCRYPT); + keyOperations.add(KeyOperation.DECRYPT); + + return JsonWebKey.fromAes(secretKey, keyOperations).setId("testKey"); + } + String generateResourceId(String suffix) { if (interceptorManager.isPlaybackMode()) { return suffix; diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes128Cbc.json b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes128Cbc.json new file mode 100644 index 0000000000000..ef57284a590ce --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes128Cbc.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes128CbcPad.json b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes128CbcPad.json new file mode 100644 index 0000000000000..ef57284a590ce --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes128CbcPad.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes128Gcm.json b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes128Gcm.json new file mode 100644 index 0000000000000..ef57284a590ce --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes128Gcm.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes192Cbc.json b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes192Cbc.json new file mode 100644 index 0000000000000..ef57284a590ce --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes192Cbc.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes192CbcPad.json b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes192CbcPad.json new file mode 100644 index 0000000000000..ef57284a590ce --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes192CbcPad.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes192Gcm.json b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes192Gcm.json new file mode 100644 index 0000000000000..ef57284a590ce --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes192Gcm.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes256Cbc.json b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes256Cbc.json new file mode 100644 index 0000000000000..ef57284a590ce --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes256Cbc.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes256CbcPad.json b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes256CbcPad.json new file mode 100644 index 0000000000000..ef57284a590ce --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes256CbcPad.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes256Gcm.json b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes256Gcm.json new file mode 100644 index 0000000000000..ef57284a590ce --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/resources/session-records/encryptDecryptLocalAes256Gcm.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +}