Skip to content

Commit cbbcb1c

Browse files
Remove use of BouncyCastle from JceMasterKey
1 parent 32580c5 commit cbbcb1c

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
## 1.6.1 -- Unreleased
44
### Maintenance
5-
* Add support for standard test vectors via `testVectorZip` system property.
5+
* Add support for standard test vectors via `testVectorZip` system property.
6+
* No longer require use of BouncyCastle with RSA `JceMasterKey`s
67

78
## 1.6.0 -- 2019-05-31
89

src/main/java/com/amazonaws/encryptionsdk/jce/JceMasterKey.java

+54-8
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,22 @@
2424
import java.security.PrivateKey;
2525
import java.security.PublicKey;
2626
import java.security.SecureRandom;
27+
import java.security.spec.AlgorithmParameterSpec;
28+
import java.security.spec.MGF1ParameterSpec;
2729
import java.util.ArrayList;
2830
import java.util.Arrays;
2931
import java.util.Collection;
3032
import java.util.List;
3133
import java.util.Map;
3234
import java.util.logging.Logger;
35+
import java.util.regex.Matcher;
3336
import java.util.regex.Pattern;
3437

3538
import javax.crypto.Cipher;
3639
import javax.crypto.SecretKey;
3740
import javax.crypto.spec.GCMParameterSpec;
41+
import javax.crypto.spec.OAEPParameterSpec;
42+
import javax.crypto.spec.PSource;
3843
import javax.crypto.spec.SecretKeySpec;
3944

4045
import com.amazonaws.encryptionsdk.CryptoAlgorithm;
@@ -237,17 +242,58 @@ public WrappingData(final Cipher cipher, final byte[] extraInfo) {
237242
}
238243

239244
private static class Rsa extends JceMasterKey {
245+
// MGF1 with SHA-224 isn't really supported, but we include it in the regex because we need it
246+
// for proper handling of the algorithm.
240247
private static final Pattern SUPPORTED_TRANSFORMATIONS =
241-
Pattern.compile("RSA/ECB/(?:PKCS1Padding|OAEPWithSHA-(?:1|256|384|512)AndMGF1Padding)",
248+
Pattern.compile("RSA/ECB/(?:PKCS1Padding|OAEPWith(SHA-(?:1|224|256|384|512))AndMGF1Padding)",
242249
Pattern.CASE_INSENSITIVE);
250+
private final AlgorithmParameterSpec parameterSpec_;
243251
private final String transformation_;
244252

245253
private Rsa(PublicKey wrappingKey, PrivateKey unwrappingKey, String providerName, String keyId,
246254
String transformation) {
247255
super(wrappingKey, unwrappingKey, providerName, keyId);
248-
transformation_ = transformation;
249-
if (!SUPPORTED_TRANSFORMATIONS.matcher(transformation_).matches()) {
250-
LOGGER.warning(transformation_ + " is not officially supported by the JceMasterKey");
256+
257+
final Matcher matcher = SUPPORTED_TRANSFORMATIONS.matcher(transformation);
258+
if (matcher.matches()) {
259+
final String hashUnknownCase = matcher.group(1);
260+
if (hashUnknownCase != null) {
261+
// OAEP mode a.k.a PKCS #1v2
262+
final String hash = hashUnknownCase.toUpperCase();
263+
transformation_ = "RSA/ECB/OAEPPadding";
264+
265+
final MGF1ParameterSpec mgf1Spec;
266+
switch (hash) {
267+
case "SHA-1":
268+
mgf1Spec = MGF1ParameterSpec.SHA1;
269+
break;
270+
case "SHA-224":
271+
LOGGER.warning(transformation + " is not officially supported by the JceMasterKey");
272+
mgf1Spec = MGF1ParameterSpec.SHA224;
273+
break;
274+
case "SHA-256":
275+
mgf1Spec = MGF1ParameterSpec.SHA256;
276+
break;
277+
case "SHA-384":
278+
mgf1Spec = MGF1ParameterSpec.SHA384;
279+
break;
280+
case "SHA-512":
281+
mgf1Spec = MGF1ParameterSpec.SHA512;
282+
break;
283+
default:
284+
throw new IllegalArgumentException("Unsupported algorithm: " + transformation);
285+
}
286+
parameterSpec_ = new OAEPParameterSpec(hash, "MGF1", mgf1Spec, PSource.PSpecified.DEFAULT);
287+
} else {
288+
// PKCS #1 v1.x
289+
transformation_ = transformation;
290+
parameterSpec_ = null;
291+
}
292+
} else {
293+
LOGGER.warning(transformation + " is not officially supported by the JceMasterKey");
294+
// Unsupported transformation, just use exactly what we are given
295+
transformation_ = transformation;
296+
parameterSpec_ = null;
251297
}
252298
}
253299

@@ -256,8 +302,8 @@ protected WrappingData buildWrappingCipher(Key key, Map<String, String> encrypti
256302
throws GeneralSecurityException {
257303
// We require BouncyCastle to avoid some bugs in the default Java implementation
258304
// of OAEP.
259-
final Cipher cipher = Cipher.getInstance(transformation_, "BC");
260-
cipher.init(Cipher.ENCRYPT_MODE, key);
305+
final Cipher cipher = Cipher.getInstance(transformation_);
306+
cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec_);
261307
return new WrappingData(cipher, EMPTY_ARRAY);
262308
}
263309

@@ -269,8 +315,8 @@ protected Cipher buildUnwrappingCipher(Key key, byte[] extraInfo, int offset,
269315
}
270316
// We require BouncyCastle to avoid some bugs in the default Java implementation
271317
// of OAEP.
272-
final Cipher cipher = Cipher.getInstance(transformation_, "BC");
273-
cipher.init(Cipher.DECRYPT_MODE, key);
318+
final Cipher cipher = Cipher.getInstance(transformation_);
319+
cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec_);
274320
return cipher;
275321
}
276322
}

0 commit comments

Comments
 (0)