Skip to content

Commit

Permalink
Use the BouncyCastleProvider class directly (#84)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
johnwalker authored and bdonlan committed Nov 29, 2018
1 parent 9c61fcc commit 7db5f02
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 9 deletions.
15 changes: 7 additions & 8 deletions src/main/java/com/amazonaws/encryptionsdk/CryptoAlgorithm.java
Expand Up @@ -16,7 +16,6 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.InvalidKeyException;
import java.security.Provider;
import java.security.Security;
import java.util.EnumSet;
import java.util.HashMap;
Expand All @@ -25,6 +24,7 @@
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.amazonaws.encryptionsdk.internal.BouncyCastleConfiguration;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
Expand All @@ -33,6 +33,7 @@

import com.amazonaws.encryptionsdk.internal.Constants;
import com.amazonaws.encryptionsdk.model.CiphertextHeaders;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

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

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

/*
Expand Down
@@ -0,0 +1,37 @@
package com.amazonaws.encryptionsdk.internal;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.Security;

/**
* This API is internal and subject to change. It is used to add BouncyCastleProvider to the
* java.security.Provider list, and to provide a static reference to BouncyCastleProvider for internal
* classes.
*/
public class BouncyCastleConfiguration {
static final BouncyCastleProvider INTERNAL_BOUNCY_CASTLE_PROVIDER;
static {
BouncyCastleProvider bouncyCastleProvider;
try {
bouncyCastleProvider = new BouncyCastleProvider();
Security.addProvider(bouncyCastleProvider);
} catch (final Throwable ex) {
bouncyCastleProvider = null;
// Swallow this error. We'll either succeed or fail later with reasonable
// stacktraces.
}
INTERNAL_BOUNCY_CASTLE_PROVIDER = bouncyCastleProvider;
}

/**
* Prevent instantiation
*/
private BouncyCastleConfiguration() {
}

/**
* No-op used to force class loading on first call, which will cause the static blocks to be executed
*/
public static void init() {}
}
Expand Up @@ -18,12 +18,15 @@

import com.amazonaws.encryptionsdk.CryptoAlgorithm;

import static com.amazonaws.encryptionsdk.internal.BouncyCastleConfiguration.INTERNAL_BOUNCY_CASTLE_PROVIDER;

/**
* Provides a consistent interface across various trailing signature algorithms.
*
* NOTE: This is not a stable API and may undergo breaking changes in the future.
*/
public abstract class TrailingSignatureAlgorithm {

private TrailingSignatureAlgorithm() {
/* Do not allow arbitrary subclasses */
}
Expand Down Expand Up @@ -84,7 +87,7 @@ public String serializePublicKey(PublicKey key) {

@Override
public KeyPair generateKey() throws GeneralSecurityException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA", "BC");
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA", INTERNAL_BOUNCY_CASTLE_PROVIDER);
keyGen.initialize(ecSpec, Utils.getSecureRandom());

return keyGen.generateKeyPair();
Expand Down

0 comments on commit 7db5f02

Please sign in to comment.