Skip to content

Commit 7db5f02

Browse files
johnwalkerbdonlan
authored andcommitted
Use the BouncyCastleProvider class directly (#84)
* Use the BouncyCastleProvider class directly This avoids issues where a shaded version of BCProvider is installed in the system JCE provider list, which can result in problems when we pass an ECNamedCurveParameterSpec from a different shaded version of BC. Fixes: #68 * Add BouncyCastleConfiguration class for handling BC init This moves the BouncyCastleProvider creation from CryptoAlgorithm to BouncyCastleConfiguration, which also contains a static field for classes that must use a pegged version of BouncyCastle. A newInstance reference is included from CryptoAlgorithm to BouncyCastleConfiguration to force initialization, since it depends on BouncyCastle being on the SecurityProvider chain. * Add comments, and use static method to force class loading This adds documentation for the purpose of the BouncyCastleConfiguration class, and uses a static method call to force the BouncyCastleConfiguration class to be loaded.
1 parent 9c61fcc commit 7db5f02

File tree

3 files changed

+48
-9
lines changed

3 files changed

+48
-9
lines changed

src/main/java/com/amazonaws/encryptionsdk/CryptoAlgorithm.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import java.nio.ByteBuffer;
1717
import java.nio.ByteOrder;
1818
import java.security.InvalidKeyException;
19-
import java.security.Provider;
2019
import java.security.Security;
2120
import java.util.EnumSet;
2221
import java.util.HashMap;
@@ -25,6 +24,7 @@
2524
import javax.crypto.SecretKey;
2625
import javax.crypto.spec.SecretKeySpec;
2726

27+
import com.amazonaws.encryptionsdk.internal.BouncyCastleConfiguration;
2828
import org.bouncycastle.crypto.Digest;
2929
import org.bouncycastle.crypto.digests.SHA256Digest;
3030
import org.bouncycastle.crypto.digests.SHA384Digest;
@@ -33,6 +33,7 @@
3333

3434
import com.amazonaws.encryptionsdk.internal.Constants;
3535
import com.amazonaws.encryptionsdk.model.CiphertextHeaders;
36+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
3637

3738
/**
3839
* Describes the cryptographic algorithms available for use in this library.
@@ -103,14 +104,12 @@ public enum CryptoAlgorithm {
103104
private final int dataKeyLen_;
104105
private final boolean safeToCache_;
105106

107+
/**
108+
* This block is used to ensure static blocks of BouncyCastleConfiguration are evaluated as a dependency of
109+
* the CryptoAlgorithm class
110+
*/
106111
static {
107-
try {
108-
Security.addProvider((Provider)
109-
Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider").newInstance());
110-
} catch (final Throwable ex) {
111-
// Swallow this error. We'll either succeed or fail later with reasonable
112-
// stacktraces.
113-
}
112+
BouncyCastleConfiguration.init();
114113
}
115114

116115
/*
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.amazonaws.encryptionsdk.internal;
2+
3+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
4+
5+
import java.security.Security;
6+
7+
/**
8+
* This API is internal and subject to change. It is used to add BouncyCastleProvider to the
9+
* java.security.Provider list, and to provide a static reference to BouncyCastleProvider for internal
10+
* classes.
11+
*/
12+
public class BouncyCastleConfiguration {
13+
static final BouncyCastleProvider INTERNAL_BOUNCY_CASTLE_PROVIDER;
14+
static {
15+
BouncyCastleProvider bouncyCastleProvider;
16+
try {
17+
bouncyCastleProvider = new BouncyCastleProvider();
18+
Security.addProvider(bouncyCastleProvider);
19+
} catch (final Throwable ex) {
20+
bouncyCastleProvider = null;
21+
// Swallow this error. We'll either succeed or fail later with reasonable
22+
// stacktraces.
23+
}
24+
INTERNAL_BOUNCY_CASTLE_PROVIDER = bouncyCastleProvider;
25+
}
26+
27+
/**
28+
* Prevent instantiation
29+
*/
30+
private BouncyCastleConfiguration() {
31+
}
32+
33+
/**
34+
* No-op used to force class loading on first call, which will cause the static blocks to be executed
35+
*/
36+
public static void init() {}
37+
}

src/main/java/com/amazonaws/encryptionsdk/internal/TrailingSignatureAlgorithm.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818

1919
import com.amazonaws.encryptionsdk.CryptoAlgorithm;
2020

21+
import static com.amazonaws.encryptionsdk.internal.BouncyCastleConfiguration.INTERNAL_BOUNCY_CASTLE_PROVIDER;
22+
2123
/**
2224
* Provides a consistent interface across various trailing signature algorithms.
2325
*
2426
* NOTE: This is not a stable API and may undergo breaking changes in the future.
2527
*/
2628
public abstract class TrailingSignatureAlgorithm {
29+
2730
private TrailingSignatureAlgorithm() {
2831
/* Do not allow arbitrary subclasses */
2932
}
@@ -84,7 +87,7 @@ public String serializePublicKey(PublicKey key) {
8487

8588
@Override
8689
public KeyPair generateKey() throws GeneralSecurityException {
87-
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA", "BC");
90+
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA", INTERNAL_BOUNCY_CASTLE_PROVIDER);
8891
keyGen.initialize(ecSpec, Utils.getSecureRandom());
8992

9093
return keyGen.generateKeyPair();

0 commit comments

Comments
 (0)