diff --git a/src/examples/java/com/amazonaws/crypto/examples/EscrowedEncryptExample.java b/src/examples/java/com/amazonaws/crypto/examples/EscrowedEncryptExample.java index 32be46198..bb12f737d 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/EscrowedEncryptExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/EscrowedEncryptExample.java @@ -17,6 +17,7 @@ import com.amazonaws.encryptionsdk.DecryptRequest; import com.amazonaws.encryptionsdk.EncryptRequest; import com.amazonaws.encryptionsdk.keyrings.Keyring; +import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme; import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings; import com.amazonaws.encryptionsdk.kms.AwsKmsCmkId; @@ -94,7 +95,7 @@ private static byte[] standardEncrypt(final AwsKmsCmkId kmsArn, final PublicKey .keyNamespace("Escrow") .keyName("Escrow") .publicKey(publicEscrowKey) - .wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding") + .paddingScheme(RsaPaddingScheme.OAEP_SHA512_MGF1) .build(); // 4. Combine the providers into a single MultiKeyring @@ -138,7 +139,7 @@ private static byte[] escrowDecrypt(final byte[] cipherText, final PrivateKey pr .keyNamespace("Escrow") .keyName("Escrow") .privateKey(privateEscrowKey) - .wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding") + .paddingScheme(RsaPaddingScheme.OAEP_SHA512_MGF1) .build(); // 3. Decrypt the data with the keyring diff --git a/src/examples/java/com/amazonaws/crypto/examples/RawRsaKeyringDecryptExample.java b/src/examples/java/com/amazonaws/crypto/examples/RawRsaKeyringDecryptExample.java index a5f3ba488..b2cf3010e 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/RawRsaKeyringDecryptExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/RawRsaKeyringDecryptExample.java @@ -17,6 +17,7 @@ import com.amazonaws.encryptionsdk.AwsCryptoResult; import com.amazonaws.encryptionsdk.DecryptRequest; import com.amazonaws.encryptionsdk.keyrings.Keyring; +import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme; import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings; import java.security.KeyPair; @@ -35,7 +36,7 @@ public static byte[] decrypt(byte[] ciphertext, KeyPair keyPair) { final Keyring keyring = StandardKeyrings.rawRsaBuilder() .keyNamespace("ExampleKeyNamespace") .keyName("ExampleKeyName") - .wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding") + .paddingScheme(RsaPaddingScheme.OAEP_SHA512_MGF1) .privateKey(keyPair.getPrivate()).build(); // 3. Decrypt the ciphertext with the keyring diff --git a/src/examples/java/com/amazonaws/crypto/examples/RawRsaKeyringEncryptExample.java b/src/examples/java/com/amazonaws/crypto/examples/RawRsaKeyringEncryptExample.java index 480ac0092..82a8001f4 100644 --- a/src/examples/java/com/amazonaws/crypto/examples/RawRsaKeyringEncryptExample.java +++ b/src/examples/java/com/amazonaws/crypto/examples/RawRsaKeyringEncryptExample.java @@ -17,6 +17,7 @@ import com.amazonaws.encryptionsdk.AwsCryptoResult; import com.amazonaws.encryptionsdk.EncryptRequest; import com.amazonaws.encryptionsdk.keyrings.Keyring; +import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme; import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings; import java.nio.charset.StandardCharsets; @@ -39,7 +40,7 @@ public static byte[] encrypt(PublicKey publicKey) { final Keyring keyring = StandardKeyrings.rawRsaBuilder() .keyNamespace("ExampleKeyNamespace") .keyName("ExampleKeyName") - .wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding") + .paddingScheme(RsaPaddingScheme.OAEP_SHA512_MGF1) .publicKey(publicKey).build(); // 3. Create an encryption context diff --git a/src/main/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyring.java b/src/main/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyring.java index d41f6d683..9b8a7b453 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyring.java +++ b/src/main/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyring.java @@ -15,6 +15,7 @@ import com.amazonaws.encryptionsdk.EncryptedDataKey; import com.amazonaws.encryptionsdk.internal.JceKeyCipher; +import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme; import java.security.PrivateKey; import java.security.PublicKey; @@ -28,8 +29,8 @@ */ class RawRsaKeyring extends RawKeyring { - RawRsaKeyring(String keyNamespace, String keyName, PublicKey publicKey, PrivateKey privateKey, String transformation) { - super(keyNamespace, keyName, JceKeyCipher.rsa(publicKey, privateKey, transformation)); + RawRsaKeyring(String keyNamespace, String keyName, PublicKey publicKey, PrivateKey privateKey, RsaPaddingScheme rsaPaddingScheme) { + super(keyNamespace, keyName, JceKeyCipher.rsa(publicKey, privateKey, rsaPaddingScheme.getTransformation())); } @Override diff --git a/src/main/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringBuilder.java b/src/main/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringBuilder.java index 190143954..f3e2a9aed 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringBuilder.java +++ b/src/main/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringBuilder.java @@ -21,7 +21,7 @@ public class RawRsaKeyringBuilder { private String keyName; private PublicKey publicKey; private PrivateKey privateKey; - private String wrappingAlgorithm; + private RsaPaddingScheme paddingScheme; private RawRsaKeyringBuilder() { // Use RawRsaKeyringBuilder.standard() or StandardKeyrings.rawRsa() to instantiate @@ -81,13 +81,13 @@ public RawRsaKeyringBuilder privateKey(PrivateKey privateKey) { } /** - * The RSA algorithm to use with this keyring (required). + * The RSA padding scheme to use with this keyring (required). * - * @param wrappingAlgorithm The algorithm + * @param paddingScheme The RSA padding scheme * @return The RawRsaKeyringBuilder, for method chaining */ - public RawRsaKeyringBuilder wrappingAlgorithm(String wrappingAlgorithm) { - this.wrappingAlgorithm = wrappingAlgorithm; + public RawRsaKeyringBuilder paddingScheme(RsaPaddingScheme paddingScheme) { + this.paddingScheme = paddingScheme; return this; } @@ -97,6 +97,33 @@ public RawRsaKeyringBuilder wrappingAlgorithm(String wrappingAlgorithm) { * @return The {@link Keyring} instance */ public Keyring build() { - return new RawRsaKeyring(keyNamespace, keyName, publicKey, privateKey, wrappingAlgorithm); + return new RawRsaKeyring(keyNamespace, keyName, publicKey, privateKey, paddingScheme); + } + + public enum RsaPaddingScheme { + + PKCS1("RSA/ECB/PKCS1Padding"), + OAEP_SHA1_MGF1("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"), + OAEP_SHA256_MGF1("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"), + OAEP_SHA384_MGF1("RSA/ECB/OAEPWithSHA-384AndMGF1Padding"), + OAEP_SHA512_MGF1("RSA/ECB/OAEPWithSHA-512AndMGF1Padding"); + + private final String transformation; + + RsaPaddingScheme(String transformation) { + this.transformation = transformation; + } + + /** + * The Cipher transformation standard name as specified in + * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher + * Note: In all cases the hash function used with MGF1 is the + * same as the hash function used directly with the message. + * + * @return The transformation name + */ + public String getTransformation() { + return transformation; + } } } diff --git a/src/test/java/com/amazonaws/crypto/examples/RawRsaKeyringEncryptExampleTest.java b/src/test/java/com/amazonaws/crypto/examples/RawRsaKeyringEncryptExampleTest.java index 25a8bddf2..0329b4e48 100644 --- a/src/test/java/com/amazonaws/crypto/examples/RawRsaKeyringEncryptExampleTest.java +++ b/src/test/java/com/amazonaws/crypto/examples/RawRsaKeyringEncryptExampleTest.java @@ -16,6 +16,7 @@ import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.DecryptRequest; import com.amazonaws.encryptionsdk.keyrings.Keyring; +import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme; import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings; import org.junit.jupiter.api.Test; @@ -38,7 +39,7 @@ void testEncrypt() throws Exception { .keyNamespace("ExampleKeyNamespace") .keyName("ExampleKeyName") .privateKey(keyPair.getPrivate()) - .wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding") + .paddingScheme(RsaPaddingScheme.OAEP_SHA512_MGF1) .build(); diff --git a/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java b/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java index 8a8e8048e..078dff781 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java +++ b/src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java @@ -16,6 +16,7 @@ import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.encryptionsdk.jce.JceMasterKey; import com.amazonaws.encryptionsdk.keyrings.Keyring; +import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme; import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings; import com.amazonaws.encryptionsdk.kms.AwsKmsClientSupplier; import com.amazonaws.encryptionsdk.kms.AwsKmsCmkId; @@ -171,15 +172,27 @@ private static TestCase parseTest(String testName, Map data, Map .wrappingKey((SecretKey) key.key).build()); mks.add(JceMasterKey.getInstance((SecretKey) key.key, provId, key.keyId, "AES/GCM/NoPadding")); } else if ("rsa".equals(algorithm)) { - String transformation = "RSA/ECB/"; + final RsaPaddingScheme paddingScheme; final String padding = mkEntry.get("padding-algorithm"); if ("pkcs1".equals(padding)) { - transformation += "PKCS1Padding"; + paddingScheme = RsaPaddingScheme.PKCS1; } else if ("oaep-mgf1".equals(padding)) { - final String hashName = mkEntry.get("padding-hash") - .replace("sha", "sha-") - .toUpperCase(); - transformation += "OAEPWith" + hashName + "AndMGF1Padding"; + switch(mkEntry.get("padding-hash")) { + case "sha1": + paddingScheme = RsaPaddingScheme.OAEP_SHA1_MGF1; + break; + case "sha256": + paddingScheme = RsaPaddingScheme.OAEP_SHA256_MGF1; + break; + case "sha384": + paddingScheme = RsaPaddingScheme.OAEP_SHA384_MGF1; + break; + case "sha512": + paddingScheme = RsaPaddingScheme.OAEP_SHA512_MGF1; + break; + default: + throw new IllegalArgumentException("Unsupported padding hash:" + mkEntry.get("padding-hash")); + } } else { throw new IllegalArgumentException("Unsupported padding:" + padding); } @@ -197,8 +210,8 @@ private static TestCase parseTest(String testName, Map data, Map .privateKey(unwrappingKey) .keyNamespace(provId) .keyName(key.keyId) - .wrappingAlgorithm(transformation).build()); - mks.add(JceMasterKey.getInstance(wrappingKey, unwrappingKey, provId, key.keyId, transformation)); + .paddingScheme(paddingScheme).build()); + mks.add(JceMasterKey.getInstance(wrappingKey, unwrappingKey, provId, key.keyId, paddingScheme.getTransformation())); } else { throw new IllegalArgumentException("Unsupported algorithm: " + algorithm); } diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderCompatibilityTest.java b/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderCompatibilityTest.java index 00a1d6f58..ffe759989 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderCompatibilityTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderCompatibilityTest.java @@ -23,6 +23,7 @@ import com.amazonaws.encryptionsdk.internal.RandomBytesGenerator; import com.amazonaws.encryptionsdk.internal.Utils; import com.amazonaws.encryptionsdk.jce.JceMasterKey; +import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme; import com.amazonaws.encryptionsdk.kms.AwsKmsCmkId; import com.amazonaws.encryptionsdk.kms.KMSTestFixtures; import com.amazonaws.encryptionsdk.kms.KmsMasterKey; @@ -74,19 +75,19 @@ void testRawAesKeyringCompatibility() { @Test void testRawRsaKeyringCompatibility() throws Exception { - final String wrappingAlgorithm = "RSA/ECB/OAEPWithSHA-512AndMGF1Padding"; + final RsaPaddingScheme paddingScheme = RsaPaddingScheme.OAEP_SHA512_MGF1; final KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA"); kg.initialize(4096); KeyPair keyPair = kg.generateKeyPair(); JceMasterKey mkp = JceMasterKey.getInstance(keyPair.getPublic(), keyPair.getPrivate(), KEY_NAMESPACE, KEY_NAME, - wrappingAlgorithm); + paddingScheme.getTransformation()); Keyring keyring = StandardKeyrings.rawRsaBuilder() .keyNamespace(KEY_NAMESPACE) .keyName(KEY_NAME) .publicKey(keyPair.getPublic()) .privateKey(keyPair.getPrivate()) - .wrappingAlgorithm(wrappingAlgorithm) + .paddingScheme(paddingScheme) .build(); testCompatibility(keyring, mkp); diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringTest.java b/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringTest.java index a5ee08079..59fff4da1 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringTest.java @@ -14,6 +14,7 @@ package com.amazonaws.encryptionsdk.keyrings; import com.amazonaws.encryptionsdk.EncryptedDataKey; +import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme; import com.amazonaws.encryptionsdk.model.DecryptionMaterials; import com.amazonaws.encryptionsdk.model.EncryptionMaterials; import com.amazonaws.encryptionsdk.model.KeyBlob; @@ -37,7 +38,7 @@ class RawRsaKeyringTest { - private static final String TRANSFORMATION = "RSA/ECB/PKCS1Padding"; + private static final RsaPaddingScheme PADDING_SCHEME = RsaPaddingScheme.PKCS1; private static RawRsaKeyring keyring; @BeforeAll @@ -45,7 +46,7 @@ static void setup() throws Exception { final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); final KeyPair keyPair = keyPairGenerator.generateKeyPair(); - keyring = new RawRsaKeyring(KEYNAMESPACE, KEYNAME, keyPair.getPublic(), keyPair.getPrivate(), TRANSFORMATION); + keyring = new RawRsaKeyring(KEYNAMESPACE, KEYNAME, keyPair.getPublic(), keyPair.getPrivate(), PADDING_SCHEME); } @Test diff --git a/src/test/java/com/amazonaws/encryptionsdk/model/RsaPaddingSchemeTest.java b/src/test/java/com/amazonaws/encryptionsdk/model/RsaPaddingSchemeTest.java new file mode 100644 index 000000000..30a96988c --- /dev/null +++ b/src/test/java/com/amazonaws/encryptionsdk/model/RsaPaddingSchemeTest.java @@ -0,0 +1,31 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except + * in compliance with the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package com.amazonaws.encryptionsdk.model; + +import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme; +import org.junit.jupiter.api.Test; + +import javax.crypto.Cipher; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class RsaPaddingSchemeTest { + + @Test + void testCipherInitialization() throws Exception { + for (RsaPaddingScheme paddingScheme : RsaPaddingScheme.values()) { + assertNotNull(Cipher.getInstance(paddingScheme.getTransformation())); + } + } +}