Skip to content

Commit 2055728

Browse files
Define an enum for the RSA padding scheme (#162)
* Define an enum for the RSA padding scheme * Making RsaPaddingScheme an inner class of RawRsaKeyringBuilder * Updated comment regarding transformation
1 parent d15f988 commit 2055728

File tree

10 files changed

+104
-26
lines changed

10 files changed

+104
-26
lines changed

src/examples/java/com/amazonaws/crypto/examples/EscrowedEncryptExample.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.amazonaws.encryptionsdk.DecryptRequest;
1818
import com.amazonaws.encryptionsdk.EncryptRequest;
1919
import com.amazonaws.encryptionsdk.keyrings.Keyring;
20+
import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme;
2021
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
2122
import com.amazonaws.encryptionsdk.kms.AwsKmsCmkId;
2223

@@ -94,7 +95,7 @@ private static byte[] standardEncrypt(final AwsKmsCmkId kmsArn, final PublicKey
9495
.keyNamespace("Escrow")
9596
.keyName("Escrow")
9697
.publicKey(publicEscrowKey)
97-
.wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
98+
.paddingScheme(RsaPaddingScheme.OAEP_SHA512_MGF1)
9899
.build();
99100

100101
// 4. Combine the providers into a single MultiKeyring
@@ -138,7 +139,7 @@ private static byte[] escrowDecrypt(final byte[] cipherText, final PrivateKey pr
138139
.keyNamespace("Escrow")
139140
.keyName("Escrow")
140141
.privateKey(privateEscrowKey)
141-
.wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
142+
.paddingScheme(RsaPaddingScheme.OAEP_SHA512_MGF1)
142143
.build();
143144

144145
// 3. Decrypt the data with the keyring

src/examples/java/com/amazonaws/crypto/examples/RawRsaKeyringDecryptExample.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.amazonaws.encryptionsdk.AwsCryptoResult;
1818
import com.amazonaws.encryptionsdk.DecryptRequest;
1919
import com.amazonaws.encryptionsdk.keyrings.Keyring;
20+
import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme;
2021
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
2122

2223
import java.security.KeyPair;
@@ -35,7 +36,7 @@ public static byte[] decrypt(byte[] ciphertext, KeyPair keyPair) {
3536
final Keyring keyring = StandardKeyrings.rawRsaBuilder()
3637
.keyNamespace("ExampleKeyNamespace")
3738
.keyName("ExampleKeyName")
38-
.wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
39+
.paddingScheme(RsaPaddingScheme.OAEP_SHA512_MGF1)
3940
.privateKey(keyPair.getPrivate()).build();
4041

4142
// 3. Decrypt the ciphertext with the keyring

src/examples/java/com/amazonaws/crypto/examples/RawRsaKeyringEncryptExample.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.amazonaws.encryptionsdk.AwsCryptoResult;
1818
import com.amazonaws.encryptionsdk.EncryptRequest;
1919
import com.amazonaws.encryptionsdk.keyrings.Keyring;
20+
import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme;
2021
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
2122

2223
import java.nio.charset.StandardCharsets;
@@ -39,7 +40,7 @@ public static byte[] encrypt(PublicKey publicKey) {
3940
final Keyring keyring = StandardKeyrings.rawRsaBuilder()
4041
.keyNamespace("ExampleKeyNamespace")
4142
.keyName("ExampleKeyName")
42-
.wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
43+
.paddingScheme(RsaPaddingScheme.OAEP_SHA512_MGF1)
4344
.publicKey(publicKey).build();
4445

4546
// 3. Create an encryption context

src/main/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyring.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import com.amazonaws.encryptionsdk.EncryptedDataKey;
1717
import com.amazonaws.encryptionsdk.internal.JceKeyCipher;
18+
import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme;
1819

1920
import java.security.PrivateKey;
2021
import java.security.PublicKey;
@@ -28,8 +29,8 @@
2829
*/
2930
class RawRsaKeyring extends RawKeyring {
3031

31-
RawRsaKeyring(String keyNamespace, String keyName, PublicKey publicKey, PrivateKey privateKey, String transformation) {
32-
super(keyNamespace, keyName, JceKeyCipher.rsa(publicKey, privateKey, transformation));
32+
RawRsaKeyring(String keyNamespace, String keyName, PublicKey publicKey, PrivateKey privateKey, RsaPaddingScheme rsaPaddingScheme) {
33+
super(keyNamespace, keyName, JceKeyCipher.rsa(publicKey, privateKey, rsaPaddingScheme.getTransformation()));
3334
}
3435

3536
@Override

src/main/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringBuilder.java

+33-6
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class RawRsaKeyringBuilder {
2121
private String keyName;
2222
private PublicKey publicKey;
2323
private PrivateKey privateKey;
24-
private String wrappingAlgorithm;
24+
private RsaPaddingScheme paddingScheme;
2525

2626
private RawRsaKeyringBuilder() {
2727
// Use RawRsaKeyringBuilder.standard() or StandardKeyrings.rawRsa() to instantiate
@@ -81,13 +81,13 @@ public RawRsaKeyringBuilder privateKey(PrivateKey privateKey) {
8181
}
8282

8383
/**
84-
* The RSA algorithm to use with this keyring (required).
84+
* The RSA padding scheme to use with this keyring (required).
8585
*
86-
* @param wrappingAlgorithm The algorithm
86+
* @param paddingScheme The RSA padding scheme
8787
* @return The RawRsaKeyringBuilder, for method chaining
8888
*/
89-
public RawRsaKeyringBuilder wrappingAlgorithm(String wrappingAlgorithm) {
90-
this.wrappingAlgorithm = wrappingAlgorithm;
89+
public RawRsaKeyringBuilder paddingScheme(RsaPaddingScheme paddingScheme) {
90+
this.paddingScheme = paddingScheme;
9191
return this;
9292
}
9393

@@ -97,6 +97,33 @@ public RawRsaKeyringBuilder wrappingAlgorithm(String wrappingAlgorithm) {
9797
* @return The {@link Keyring} instance
9898
*/
9999
public Keyring build() {
100-
return new RawRsaKeyring(keyNamespace, keyName, publicKey, privateKey, wrappingAlgorithm);
100+
return new RawRsaKeyring(keyNamespace, keyName, publicKey, privateKey, paddingScheme);
101+
}
102+
103+
public enum RsaPaddingScheme {
104+
105+
PKCS1("RSA/ECB/PKCS1Padding"),
106+
OAEP_SHA1_MGF1("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"),
107+
OAEP_SHA256_MGF1("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"),
108+
OAEP_SHA384_MGF1("RSA/ECB/OAEPWithSHA-384AndMGF1Padding"),
109+
OAEP_SHA512_MGF1("RSA/ECB/OAEPWithSHA-512AndMGF1Padding");
110+
111+
private final String transformation;
112+
113+
RsaPaddingScheme(String transformation) {
114+
this.transformation = transformation;
115+
}
116+
117+
/**
118+
* The Cipher transformation standard name as specified in
119+
* https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher
120+
* Note: In all cases the hash function used with MGF1 is the
121+
* same as the hash function used directly with the message.
122+
*
123+
* @return The transformation name
124+
*/
125+
public String getTransformation() {
126+
return transformation;
127+
}
101128
}
102129
}

src/test/java/com/amazonaws/crypto/examples/RawRsaKeyringEncryptExampleTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.amazonaws.encryptionsdk.AwsCrypto;
1717
import com.amazonaws.encryptionsdk.DecryptRequest;
1818
import com.amazonaws.encryptionsdk.keyrings.Keyring;
19+
import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme;
1920
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
2021
import org.junit.jupiter.api.Test;
2122

@@ -38,7 +39,7 @@ void testEncrypt() throws Exception {
3839
.keyNamespace("ExampleKeyNamespace")
3940
.keyName("ExampleKeyName")
4041
.privateKey(keyPair.getPrivate())
41-
.wrappingAlgorithm("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
42+
.paddingScheme(RsaPaddingScheme.OAEP_SHA512_MGF1)
4243
.build();
4344

4445

src/test/java/com/amazonaws/encryptionsdk/TestVectorRunner.java

+21-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
1717
import com.amazonaws.encryptionsdk.jce.JceMasterKey;
1818
import com.amazonaws.encryptionsdk.keyrings.Keyring;
19+
import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme;
1920
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
2021
import com.amazonaws.encryptionsdk.kms.AwsKmsClientSupplier;
2122
import com.amazonaws.encryptionsdk.kms.AwsKmsCmkId;
@@ -171,15 +172,27 @@ private static TestCase parseTest(String testName, Map<String, Object> data, Map
171172
.wrappingKey((SecretKey) key.key).build());
172173
mks.add(JceMasterKey.getInstance((SecretKey) key.key, provId, key.keyId, "AES/GCM/NoPadding"));
173174
} else if ("rsa".equals(algorithm)) {
174-
String transformation = "RSA/ECB/";
175+
final RsaPaddingScheme paddingScheme;
175176
final String padding = mkEntry.get("padding-algorithm");
176177
if ("pkcs1".equals(padding)) {
177-
transformation += "PKCS1Padding";
178+
paddingScheme = RsaPaddingScheme.PKCS1;
178179
} else if ("oaep-mgf1".equals(padding)) {
179-
final String hashName = mkEntry.get("padding-hash")
180-
.replace("sha", "sha-")
181-
.toUpperCase();
182-
transformation += "OAEPWith" + hashName + "AndMGF1Padding";
180+
switch(mkEntry.get("padding-hash")) {
181+
case "sha1":
182+
paddingScheme = RsaPaddingScheme.OAEP_SHA1_MGF1;
183+
break;
184+
case "sha256":
185+
paddingScheme = RsaPaddingScheme.OAEP_SHA256_MGF1;
186+
break;
187+
case "sha384":
188+
paddingScheme = RsaPaddingScheme.OAEP_SHA384_MGF1;
189+
break;
190+
case "sha512":
191+
paddingScheme = RsaPaddingScheme.OAEP_SHA512_MGF1;
192+
break;
193+
default:
194+
throw new IllegalArgumentException("Unsupported padding hash:" + mkEntry.get("padding-hash"));
195+
}
183196
} else {
184197
throw new IllegalArgumentException("Unsupported padding:" + padding);
185198
}
@@ -197,8 +210,8 @@ private static TestCase parseTest(String testName, Map<String, Object> data, Map
197210
.privateKey(unwrappingKey)
198211
.keyNamespace(provId)
199212
.keyName(key.keyId)
200-
.wrappingAlgorithm(transformation).build());
201-
mks.add(JceMasterKey.getInstance(wrappingKey, unwrappingKey, provId, key.keyId, transformation));
213+
.paddingScheme(paddingScheme).build());
214+
mks.add(JceMasterKey.getInstance(wrappingKey, unwrappingKey, provId, key.keyId, paddingScheme.getTransformation()));
202215
} else {
203216
throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
204217
}

src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderCompatibilityTest.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.amazonaws.encryptionsdk.internal.RandomBytesGenerator;
2424
import com.amazonaws.encryptionsdk.internal.Utils;
2525
import com.amazonaws.encryptionsdk.jce.JceMasterKey;
26+
import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme;
2627
import com.amazonaws.encryptionsdk.kms.AwsKmsCmkId;
2728
import com.amazonaws.encryptionsdk.kms.KMSTestFixtures;
2829
import com.amazonaws.encryptionsdk.kms.KmsMasterKey;
@@ -74,19 +75,19 @@ void testRawAesKeyringCompatibility() {
7475

7576
@Test
7677
void testRawRsaKeyringCompatibility() throws Exception {
77-
final String wrappingAlgorithm = "RSA/ECB/OAEPWithSHA-512AndMGF1Padding";
78+
final RsaPaddingScheme paddingScheme = RsaPaddingScheme.OAEP_SHA512_MGF1;
7879
final KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA");
7980
kg.initialize(4096);
8081
KeyPair keyPair = kg.generateKeyPair();
8182

8283
JceMasterKey mkp = JceMasterKey.getInstance(keyPair.getPublic(), keyPair.getPrivate(), KEY_NAMESPACE, KEY_NAME,
83-
wrappingAlgorithm);
84+
paddingScheme.getTransformation());
8485
Keyring keyring = StandardKeyrings.rawRsaBuilder()
8586
.keyNamespace(KEY_NAMESPACE)
8687
.keyName(KEY_NAME)
8788
.publicKey(keyPair.getPublic())
8889
.privateKey(keyPair.getPrivate())
89-
.wrappingAlgorithm(wrappingAlgorithm)
90+
.paddingScheme(paddingScheme)
9091
.build();
9192

9293
testCompatibility(keyring, mkp);

src/test/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringTest.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package com.amazonaws.encryptionsdk.keyrings;
1515

1616
import com.amazonaws.encryptionsdk.EncryptedDataKey;
17+
import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme;
1718
import com.amazonaws.encryptionsdk.model.DecryptionMaterials;
1819
import com.amazonaws.encryptionsdk.model.EncryptionMaterials;
1920
import com.amazonaws.encryptionsdk.model.KeyBlob;
@@ -37,15 +38,15 @@
3738

3839
class RawRsaKeyringTest {
3940

40-
private static final String TRANSFORMATION = "RSA/ECB/PKCS1Padding";
41+
private static final RsaPaddingScheme PADDING_SCHEME = RsaPaddingScheme.PKCS1;
4142
private static RawRsaKeyring keyring;
4243

4344
@BeforeAll
4445
static void setup() throws Exception {
4546
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
4647
keyPairGenerator.initialize(2048);
4748
final KeyPair keyPair = keyPairGenerator.generateKeyPair();
48-
keyring = new RawRsaKeyring(KEYNAMESPACE, KEYNAME, keyPair.getPublic(), keyPair.getPrivate(), TRANSFORMATION);
49+
keyring = new RawRsaKeyring(KEYNAMESPACE, KEYNAME, keyPair.getPublic(), keyPair.getPrivate(), PADDING_SCHEME);
4950
}
5051

5152
@Test
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
5+
* in compliance with the License. A copy of the License is located at
6+
*
7+
* http://aws.amazon.com/apache2.0
8+
*
9+
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package com.amazonaws.encryptionsdk.model;
15+
16+
import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder.RsaPaddingScheme;
17+
import org.junit.jupiter.api.Test;
18+
19+
import javax.crypto.Cipher;
20+
21+
import static org.junit.jupiter.api.Assertions.assertNotNull;
22+
23+
class RsaPaddingSchemeTest {
24+
25+
@Test
26+
void testCipherInitialization() throws Exception {
27+
for (RsaPaddingScheme paddingScheme : RsaPaddingScheme.values()) {
28+
assertNotNull(Cipher.getInstance(paddingScheme.getTransformation()));
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)