diff --git a/privateca/cloud-client/src/main/java/privateca/CreateCertificate.java b/privateca/cloud-client/src/main/java/privateca/CreateCertificate.java
index 8be4f175bc4..dd716f48439 100644
--- a/privateca/cloud-client/src/main/java/privateca/CreateCertificate.java
+++ b/privateca/cloud-client/src/main/java/privateca/CreateCertificate.java
@@ -18,8 +18,6 @@
// [START privateca_create_certificate]
import com.google.api.core.ApiFuture;
-import com.google.cloud.kms.v1.CryptoKeyVersionName;
-import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.cloud.security.privateca.v1.CaPoolName;
import com.google.cloud.security.privateca.v1.Certificate;
import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient;
@@ -46,24 +44,14 @@ public static void main(String[] args)
throws InterruptedException, ExecutionException, IOException {
// TODO(developer): Replace these variables before running the sample.
- // To sign and issue a certificate, a public key is essential. Here, we are making use
- // of Cloud KMS to retrieve an already created public key. Specify the following details to
- // retrieve the key. For more info, see: https://cloud.google.com/kms/docs/retrieve-public-key
- String project = "your-project-id";
- String kmsLocation = "kms-location";
- String keyRingId = "your-ring-id";
- String keyId = "your-key-id";
- String keyVersionId = "your-version-id";
-
- // Retrieve the public key from Cloud KMS.
- ByteString publicKeyBytes =
- retrievePublicKey(project, kmsLocation, keyRingId, keyId, keyVersionId);
-
+ // publicKeyBytes: Public key used in signing the certificates.
// location: For a list of locations, see:
// https://cloud.google.com/certificate-authority-service/docs/locations
// caPoolName: Set a unique name for the CA pool.
// certificateAuthorityName: The name of the certificate authority which issues the certificate.
// certificateName: Set a unique name for the certificate.
+ String project = "your-project-id";
+ ByteString publicKeyBytes = ByteString.copyFrom(new byte[] {});
String location = "ca-location";
String caPoolName = "ca-pool-name";
String certificateAuthorityName = "certificate-authority-name";
@@ -74,7 +62,8 @@ public static void main(String[] args)
}
// Create a Certificate which is issued by the Certificate Authority present in the CA Pool.
- // The key used to sign the certificate is created by the Cloud KMS.
+ // The public key used to sign the certificate can be generated using any crypto
+ // library/framework.
public static void createCertificate(
String project,
String location,
@@ -99,7 +88,7 @@ public static void createCertificate(
String domainName = "dnsname.com";
long certificateLifetime = 1000L;
- // Set the Public Key and its format as obtained from the Cloud KMS.
+ // Set the Public Key and its format.
PublicKey publicKey =
PublicKey.newBuilder().setKey(publicKeyBytes).setFormat(KeyFormat.PEM).build();
@@ -163,24 +152,5 @@ public static void createCertificate(
System.out.println(response.getPemCertificateChainList());
}
}
-
- // Get the public Key used for signing the certificate from Cloud KMS.
- public static ByteString retrievePublicKey(
- String project, String kmsLocation, String keyRingId, String keyId, String keyVersionId)
- throws IOException {
- // Initialize client that will be used to send requests. This client only needs to be created
- // once, and can be reused for multiple requests. After completing all of your requests, call
- // the `client.close()` method on the client to safely
- // clean up any remaining background resources.
- try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
-
- CryptoKeyVersionName keyVersionName =
- CryptoKeyVersionName.of(project, kmsLocation, keyRingId, keyId, keyVersionId);
- com.google.cloud.kms.v1.PublicKey publicKey = client.getPublicKey(keyVersionName);
-
- ByteString publicKeyBytes = publicKey.getPemBytes();
- return publicKeyBytes;
- }
- }
}
// [END privateca_create_certificate]
diff --git a/privateca/cloud-client/src/test/java/privateca/SnippetsIT.java b/privateca/cloud-client/src/test/java/privateca/SnippetsIT.java
index 6764556402a..f9903a9bf17 100644
--- a/privateca/cloud-client/src/test/java/privateca/SnippetsIT.java
+++ b/privateca/cloud-client/src/test/java/privateca/SnippetsIT.java
@@ -18,17 +18,6 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
-import com.google.cloud.kms.v1.CreateKeyRingRequest;
-import com.google.cloud.kms.v1.CryptoKey;
-import com.google.cloud.kms.v1.CryptoKey.CryptoKeyPurpose;
-import com.google.cloud.kms.v1.CryptoKeyVersion;
-import com.google.cloud.kms.v1.CryptoKeyVersion.CryptoKeyVersionAlgorithm;
-import com.google.cloud.kms.v1.CryptoKeyVersionName;
-import com.google.cloud.kms.v1.CryptoKeyVersionTemplate;
-import com.google.cloud.kms.v1.KeyManagementServiceClient;
-import com.google.cloud.kms.v1.KeyRing;
-import com.google.cloud.kms.v1.KeyRingName;
-import com.google.cloud.kms.v1.LocationName;
import com.google.cloud.security.privateca.v1.CaPoolName;
import com.google.cloud.security.privateca.v1.Certificate;
import com.google.cloud.security.privateca.v1.CertificateAuthority;
@@ -38,11 +27,22 @@
import com.google.protobuf.ByteString;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.OutputStreamWriter;
import java.io.PrintStream;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.bouncycastle.util.io.pem.PemWriter;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
@@ -57,15 +57,12 @@ public class SnippetsIT {
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
private static String LOCATION;
- private static String KMS_LOCATION;
private static String CA_POOL_NAME;
private static String CA_POOL_NAME_DELETE;
private static String CA_NAME;
private static String CA_NAME_DELETE;
private static String CERTIFICATE_NAME;
- private static String KEY_RING_ID;
- private static String KEY_ID;
- private static String VERSION_ID;
+ private static int KEY_SIZE;
private ByteArrayOutputStream stdOut;
@@ -77,24 +74,24 @@ public static void reqEnvVar(String envVarName) {
}
@BeforeClass
- public static void setUp() throws InterruptedException, ExecutionException, IOException {
+ public static void setUp()
+ throws IOException, ExecutionException, NoSuchProviderException, NoSuchAlgorithmException,
+ InterruptedException {
reqEnvVar("GOOGLE_APPLICATION_CREDENTIALS");
reqEnvVar("GOOGLE_CLOUD_PROJECT");
LOCATION = "asia-south1";
- KMS_LOCATION = "global";
CA_POOL_NAME = "ca-pool-" + UUID.randomUUID().toString();
CA_POOL_NAME_DELETE = "ca-pool-" + UUID.randomUUID().toString();
CA_NAME = "ca-name-" + UUID.randomUUID().toString();
CA_NAME_DELETE = "ca-name-" + UUID.randomUUID().toString();
CERTIFICATE_NAME = "certificate-name-" + UUID.randomUUID().toString();
- KEY_RING_ID = "key-ring-id-" + UUID.randomUUID().toString();
- KEY_ID = "key-id-" + UUID.randomUUID().toString();
- VERSION_ID = "1";
+ KEY_SIZE = 2048; // Default key size
// Create CA Pool.
privateca.CreateCaPool.createCaPool(PROJECT_ID, LOCATION, CA_POOL_NAME);
privateca.CreateCaPool.createCaPool(PROJECT_ID, LOCATION, CA_POOL_NAME_DELETE);
+ sleep(5);
// Create and Enable Certificate Authorities.
privateca.CreateCertificateAuthority.createCertificateAuthority(
@@ -105,17 +102,27 @@ public static void setUp() throws InterruptedException, ExecutionException, IOEx
privateca.EnableCertificateAuthority.enableCertificateAuthority(
PROJECT_ID, LOCATION, CA_POOL_NAME, CA_NAME);
- // Create Asymmetric Sign Key used to sign certificate, with Cloud KMS.
- createKeyRing();
- sleep(5);
- createAsymmetricSignKey();
+ // Create an asymmetric key pair using Bouncy Castle crypto framework.
+ KeyPair asymmetricKeyPair = createAsymmetricKeyPair();
+
+ // Cast the keys to their respective components.
+ RSAPublicKey publicKey = (RSAPublicKey) asymmetricKeyPair.getPublic();
+ RSAPrivateKey privateKey = (RSAPrivateKey) asymmetricKeyPair.getPrivate();
+
+ // Construct the PemObject for public and private keys.
+ PemObject publicKeyPemObject = new PemObject("PUBLIC KEY", publicKey.getEncoded());
+ PemObject privateKeyPemObject = new PemObject("PRIVATE KEY", privateKey.getEncoded());
+
+ // Only the public key will be used to create the certificate.
+ ByteString publicKeyByteString = convertToPemEncodedByteString(publicKeyPemObject);
- // Retrieve public key from Cloud KMS and Create Certificate.
- ByteString publicKey =
- privateca.CreateCertificate.retrievePublicKey(
- PROJECT_ID, KMS_LOCATION, KEY_RING_ID, KEY_ID, VERSION_ID);
+ // TODO (Developers): Save the private key by writing it to a file and
+ // TODO (cont): use it to verify the issued certificate.
+ ByteString privateKeyByteString = convertToPemEncodedByteString(privateKeyPemObject);
+
+ // Create certificate with the above generated public key.
privateca.CreateCertificate.createCertificate(
- PROJECT_ID, LOCATION, CA_POOL_NAME, CA_NAME, CERTIFICATE_NAME, publicKey);
+ PROJECT_ID, LOCATION, CA_POOL_NAME, CA_NAME, CERTIFICATE_NAME, publicKeyByteString);
sleep(5);
}
@@ -125,9 +132,6 @@ public static void cleanUp() throws InterruptedException, ExecutionException, IO
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(stdOut));
- // De-provision public key.
- cleanupCertificateSignKey();
-
// Delete CA and CA pool.
privateca.DeleteCertificateAuthority.deleteCertificateAuthority(
PROJECT_ID, LOCATION, CA_POOL_NAME, CA_NAME);
@@ -138,71 +142,34 @@ public static void cleanUp() throws InterruptedException, ExecutionException, IO
System.setOut(null);
}
- // Create a new key ring.
- public static void createKeyRing() throws IOException {
- // Initialize client that will be used to send requests. This client only
- // needs to be created once, and can be reused for multiple requests. After
- // completing all of your requests, call the "close" method on the client to
- // safely clean up any remaining background resources.
- try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
- // Build the parent name from the project and location.
- LocationName locationName = LocationName.of(PROJECT_ID, KMS_LOCATION);
-
- // Build the key ring to create.
- KeyRing keyRing = KeyRing.newBuilder().setName(locationName.toString()).build();
-
- // Create the key ring.
- KeyRing createdKeyRing =
- client.createKeyRing(
- CreateKeyRingRequest.newBuilder()
- .setParent(locationName.toString())
- .setKeyRing(keyRing)
- .setKeyRingId(KEY_RING_ID)
- .build());
- System.out.printf("Created key ring: %s%n", createdKeyRing.getName());
- }
+ // Wait for the specified amount of time.
+ public static void sleep(int seconds) throws InterruptedException {
+ TimeUnit.SECONDS.sleep(seconds);
}
- // Create a new asymmetric key for the purpose of signing and verifying data.
- public static void createAsymmetricSignKey() throws IOException {
- // Initialize client that will be used to send requests. This client only
- // needs to be created once, and can be reused for multiple requests. After
- // completing all of your requests, call the "close" method on the client to
- // safely clean up any remaining background resources.
- try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
- // Build the parent name from the project, location, and key ring.
- KeyRingName keyRingName = KeyRingName.of(PROJECT_ID, KMS_LOCATION, KEY_RING_ID);
-
- // Build the asymmetric key to create.
- CryptoKey key =
- CryptoKey.newBuilder()
- .setPurpose(CryptoKeyPurpose.ASYMMETRIC_SIGN)
- .setVersionTemplate(
- CryptoKeyVersionTemplate.newBuilder()
- .setAlgorithm(CryptoKeyVersionAlgorithm.RSA_SIGN_PKCS1_2048_SHA256))
- .build();
-
- // Create the key.
- CryptoKey createdKey = client.createCryptoKey(keyRingName, KEY_ID, key);
- System.out.printf("Created asymmetric key: %s%n", createdKey.getName());
- }
- }
+ // Create an asymmetric key pair to be used in certificate signing.
+ public static KeyPair createAsymmetricKeyPair()
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ Security.addProvider(new BouncyCastleProvider());
- public static void cleanupCertificateSignKey() throws IOException, InterruptedException {
- try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
- CryptoKeyVersionName cryptoKeyVersionName =
- CryptoKeyVersionName.of(PROJECT_ID, KMS_LOCATION, KEY_RING_ID, KEY_ID, VERSION_ID);
- // Destroy the crypto key version.
- CryptoKeyVersion cryptoKeyVersion = client.destroyCryptoKeyVersion(cryptoKeyVersionName);
- sleep(5);
- // If the response has destroy time, then the version is successfully destroyed.
- Assert.assertTrue(cryptoKeyVersion.hasDestroyTime());
- }
+ // Generate the key pair with RSA algorithm using Bouncy Castle (BC).
+ KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
+ generator.initialize(KEY_SIZE);
+ KeyPair keyPair = generator.generateKeyPair();
+
+ return keyPair;
}
- // Wait for the specified amount of time.
- public static void sleep(int seconds) throws InterruptedException {
- TimeUnit.SECONDS.sleep(seconds);
+ // Convert the encoded PemObject to ByteString.
+ public static ByteString convertToPemEncodedByteString(PemObject pemEncodedKey)
+ throws IOException {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ PemWriter pemWriter = new PemWriter(new OutputStreamWriter(byteArrayOutputStream));
+ pemWriter.writeObject(pemEncodedKey);
+ pemWriter.close();
+ ByteString keyByteString = ByteString.copyFrom(byteArrayOutputStream.toByteArray());
+
+ return keyByteString;
}
@Before
diff --git a/privateca/pom.xml b/privateca/pom.xml
index 62464ee33e4..45035eaae95 100644
--- a/privateca/pom.xml
+++ b/privateca/pom.xml
@@ -54,7 +54,11 @@
google-cloud-security-private-ca
1.1.0
-
+
+ org.bouncycastle
+ bcpkix-jdk15on
+ 1.58
+
com.google.cloud
google-cloud-kms