Skip to content

Commit ea7843d

Browse files
fix: changed the crypto public key provider to Bouncy Castle (#223)
* fix: changed the crypto public key provider to Bouncy Castle * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/master/packages/owl-bot/README.md * fix: changed the crypto public key provider to Bouncy Castle * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/master/packages/owl-bot/README.md * refactor: tweaked key creation acc to review comments * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/master/packages/owl-bot/README.md * docs: lint changes acc to review comments * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/master/packages/owl-bot/README.md Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 696bbc4 commit ea7843d

File tree

3 files changed

+70
-129
lines changed

3 files changed

+70
-129
lines changed

privateca/cloud-client/src/main/java/privateca/CreateCertificate.java

+6-36
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
// [START privateca_create_certificate]
1919

2020
import com.google.api.core.ApiFuture;
21-
import com.google.cloud.kms.v1.CryptoKeyVersionName;
22-
import com.google.cloud.kms.v1.KeyManagementServiceClient;
2321
import com.google.cloud.security.privateca.v1.CaPoolName;
2422
import com.google.cloud.security.privateca.v1.Certificate;
2523
import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient;
@@ -46,24 +44,14 @@ public static void main(String[] args)
4644
throws InterruptedException, ExecutionException, IOException {
4745
// TODO(developer): Replace these variables before running the sample.
4846

49-
// To sign and issue a certificate, a public key is essential. Here, we are making use
50-
// of Cloud KMS to retrieve an already created public key. Specify the following details to
51-
// retrieve the key. For more info, see: https://cloud.google.com/kms/docs/retrieve-public-key
52-
String project = "your-project-id";
53-
String kmsLocation = "kms-location";
54-
String keyRingId = "your-ring-id";
55-
String keyId = "your-key-id";
56-
String keyVersionId = "your-version-id";
57-
58-
// Retrieve the public key from Cloud KMS.
59-
ByteString publicKeyBytes =
60-
retrievePublicKey(project, kmsLocation, keyRingId, keyId, keyVersionId);
61-
47+
// publicKeyBytes: Public key used in signing the certificates.
6248
// location: For a list of locations, see:
6349
// https://cloud.google.com/certificate-authority-service/docs/locations
6450
// caPoolName: Set a unique name for the CA pool.
6551
// certificateAuthorityName: The name of the certificate authority which issues the certificate.
6652
// certificateName: Set a unique name for the certificate.
53+
String project = "your-project-id";
54+
ByteString publicKeyBytes = ByteString.copyFrom(new byte[] {});
6755
String location = "ca-location";
6856
String caPoolName = "ca-pool-name";
6957
String certificateAuthorityName = "certificate-authority-name";
@@ -74,7 +62,8 @@ public static void main(String[] args)
7462
}
7563

7664
// Create a Certificate which is issued by the Certificate Authority present in the CA Pool.
77-
// The key used to sign the certificate is created by the Cloud KMS.
65+
// The public key used to sign the certificate can be generated using any crypto
66+
// library/framework.
7867
public static void createCertificate(
7968
String project,
8069
String location,
@@ -99,7 +88,7 @@ public static void createCertificate(
9988
String domainName = "dnsname.com";
10089
long certificateLifetime = 1000L;
10190

102-
// Set the Public Key and its format as obtained from the Cloud KMS.
91+
// Set the Public Key and its format.
10392
PublicKey publicKey =
10493
PublicKey.newBuilder().setKey(publicKeyBytes).setFormat(KeyFormat.PEM).build();
10594

@@ -163,24 +152,5 @@ public static void createCertificate(
163152
System.out.println(response.getPemCertificateChainList());
164153
}
165154
}
166-
167-
// Get the public Key used for signing the certificate from Cloud KMS.
168-
public static ByteString retrievePublicKey(
169-
String project, String kmsLocation, String keyRingId, String keyId, String keyVersionId)
170-
throws IOException {
171-
// Initialize client that will be used to send requests. This client only needs to be created
172-
// once, and can be reused for multiple requests. After completing all of your requests, call
173-
// the `client.close()` method on the client to safely
174-
// clean up any remaining background resources.
175-
try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
176-
177-
CryptoKeyVersionName keyVersionName =
178-
CryptoKeyVersionName.of(project, kmsLocation, keyRingId, keyId, keyVersionId);
179-
com.google.cloud.kms.v1.PublicKey publicKey = client.getPublicKey(keyVersionName);
180-
181-
ByteString publicKeyBytes = publicKey.getPemBytes();
182-
return publicKeyBytes;
183-
}
184-
}
185155
}
186156
// [END privateca_create_certificate]

privateca/cloud-client/src/test/java/privateca/SnippetsIT.java

+59-92
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,6 @@
1818
import static com.google.common.truth.Truth.assertThat;
1919
import static com.google.common.truth.Truth.assertWithMessage;
2020

21-
import com.google.cloud.kms.v1.CreateKeyRingRequest;
22-
import com.google.cloud.kms.v1.CryptoKey;
23-
import com.google.cloud.kms.v1.CryptoKey.CryptoKeyPurpose;
24-
import com.google.cloud.kms.v1.CryptoKeyVersion;
25-
import com.google.cloud.kms.v1.CryptoKeyVersion.CryptoKeyVersionAlgorithm;
26-
import com.google.cloud.kms.v1.CryptoKeyVersionName;
27-
import com.google.cloud.kms.v1.CryptoKeyVersionTemplate;
28-
import com.google.cloud.kms.v1.KeyManagementServiceClient;
29-
import com.google.cloud.kms.v1.KeyRing;
30-
import com.google.cloud.kms.v1.KeyRingName;
31-
import com.google.cloud.kms.v1.LocationName;
3221
import com.google.cloud.security.privateca.v1.CaPoolName;
3322
import com.google.cloud.security.privateca.v1.Certificate;
3423
import com.google.cloud.security.privateca.v1.CertificateAuthority;
@@ -38,11 +27,22 @@
3827
import com.google.protobuf.ByteString;
3928
import java.io.ByteArrayOutputStream;
4029
import java.io.IOException;
30+
import java.io.OutputStreamWriter;
4131
import java.io.PrintStream;
32+
import java.security.KeyPair;
33+
import java.security.KeyPairGenerator;
34+
import java.security.NoSuchAlgorithmException;
35+
import java.security.NoSuchProviderException;
36+
import java.security.Security;
37+
import java.security.interfaces.RSAPrivateKey;
38+
import java.security.interfaces.RSAPublicKey;
4239
import java.util.UUID;
4340
import java.util.concurrent.ExecutionException;
4441
import java.util.concurrent.TimeUnit;
4542
import java.util.concurrent.TimeoutException;
43+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
44+
import org.bouncycastle.util.io.pem.PemObject;
45+
import org.bouncycastle.util.io.pem.PemWriter;
4646
import org.junit.After;
4747
import org.junit.AfterClass;
4848
import org.junit.Assert;
@@ -57,15 +57,12 @@ public class SnippetsIT {
5757

5858
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
5959
private static String LOCATION;
60-
private static String KMS_LOCATION;
6160
private static String CA_POOL_NAME;
6261
private static String CA_POOL_NAME_DELETE;
6362
private static String CA_NAME;
6463
private static String CA_NAME_DELETE;
6564
private static String CERTIFICATE_NAME;
66-
private static String KEY_RING_ID;
67-
private static String KEY_ID;
68-
private static String VERSION_ID;
65+
private static int KEY_SIZE;
6966

7067
private ByteArrayOutputStream stdOut;
7168

@@ -77,24 +74,24 @@ public static void reqEnvVar(String envVarName) {
7774
}
7875

7976
@BeforeClass
80-
public static void setUp() throws InterruptedException, ExecutionException, IOException {
77+
public static void setUp()
78+
throws IOException, ExecutionException, NoSuchProviderException, NoSuchAlgorithmException,
79+
InterruptedException {
8180
reqEnvVar("GOOGLE_APPLICATION_CREDENTIALS");
8281
reqEnvVar("GOOGLE_CLOUD_PROJECT");
8382

8483
LOCATION = "asia-south1";
85-
KMS_LOCATION = "global";
8684
CA_POOL_NAME = "ca-pool-" + UUID.randomUUID().toString();
8785
CA_POOL_NAME_DELETE = "ca-pool-" + UUID.randomUUID().toString();
8886
CA_NAME = "ca-name-" + UUID.randomUUID().toString();
8987
CA_NAME_DELETE = "ca-name-" + UUID.randomUUID().toString();
9088
CERTIFICATE_NAME = "certificate-name-" + UUID.randomUUID().toString();
91-
KEY_RING_ID = "key-ring-id-" + UUID.randomUUID().toString();
92-
KEY_ID = "key-id-" + UUID.randomUUID().toString();
93-
VERSION_ID = "1";
89+
KEY_SIZE = 2048; // Default key size
9490

9591
// Create CA Pool.
9692
privateca.CreateCaPool.createCaPool(PROJECT_ID, LOCATION, CA_POOL_NAME);
9793
privateca.CreateCaPool.createCaPool(PROJECT_ID, LOCATION, CA_POOL_NAME_DELETE);
94+
sleep(5);
9895

9996
// Create and Enable Certificate Authorities.
10097
privateca.CreateCertificateAuthority.createCertificateAuthority(
@@ -105,17 +102,27 @@ public static void setUp() throws InterruptedException, ExecutionException, IOEx
105102
privateca.EnableCertificateAuthority.enableCertificateAuthority(
106103
PROJECT_ID, LOCATION, CA_POOL_NAME, CA_NAME);
107104

108-
// Create Asymmetric Sign Key used to sign certificate, with Cloud KMS.
109-
createKeyRing();
110-
sleep(5);
111-
createAsymmetricSignKey();
105+
// Create an asymmetric key pair using Bouncy Castle crypto framework.
106+
KeyPair asymmetricKeyPair = createAsymmetricKeyPair();
107+
108+
// Cast the keys to their respective components.
109+
RSAPublicKey publicKey = (RSAPublicKey) asymmetricKeyPair.getPublic();
110+
RSAPrivateKey privateKey = (RSAPrivateKey) asymmetricKeyPair.getPrivate();
111+
112+
// Construct the PemObject for public and private keys.
113+
PemObject publicKeyPemObject = new PemObject("PUBLIC KEY", publicKey.getEncoded());
114+
PemObject privateKeyPemObject = new PemObject("PRIVATE KEY", privateKey.getEncoded());
115+
116+
// Only the public key will be used to create the certificate.
117+
ByteString publicKeyByteString = convertToPemEncodedByteString(publicKeyPemObject);
112118

113-
// Retrieve public key from Cloud KMS and Create Certificate.
114-
ByteString publicKey =
115-
privateca.CreateCertificate.retrievePublicKey(
116-
PROJECT_ID, KMS_LOCATION, KEY_RING_ID, KEY_ID, VERSION_ID);
119+
// TODO (Developers): Save the private key by writing it to a file and
120+
// TODO (cont): use it to verify the issued certificate.
121+
ByteString privateKeyByteString = convertToPemEncodedByteString(privateKeyPemObject);
122+
123+
// Create certificate with the above generated public key.
117124
privateca.CreateCertificate.createCertificate(
118-
PROJECT_ID, LOCATION, CA_POOL_NAME, CA_NAME, CERTIFICATE_NAME, publicKey);
125+
PROJECT_ID, LOCATION, CA_POOL_NAME, CA_NAME, CERTIFICATE_NAME, publicKeyByteString);
119126
sleep(5);
120127
}
121128

@@ -125,9 +132,6 @@ public static void cleanUp() throws InterruptedException, ExecutionException, IO
125132
ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
126133
System.setOut(new PrintStream(stdOut));
127134

128-
// De-provision public key.
129-
cleanupCertificateSignKey();
130-
131135
// Delete CA and CA pool.
132136
privateca.DeleteCertificateAuthority.deleteCertificateAuthority(
133137
PROJECT_ID, LOCATION, CA_POOL_NAME, CA_NAME);
@@ -138,71 +142,34 @@ public static void cleanUp() throws InterruptedException, ExecutionException, IO
138142
System.setOut(null);
139143
}
140144

141-
// Create a new key ring.
142-
public static void createKeyRing() throws IOException {
143-
// Initialize client that will be used to send requests. This client only
144-
// needs to be created once, and can be reused for multiple requests. After
145-
// completing all of your requests, call the "close" method on the client to
146-
// safely clean up any remaining background resources.
147-
try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
148-
// Build the parent name from the project and location.
149-
LocationName locationName = LocationName.of(PROJECT_ID, KMS_LOCATION);
150-
151-
// Build the key ring to create.
152-
KeyRing keyRing = KeyRing.newBuilder().setName(locationName.toString()).build();
153-
154-
// Create the key ring.
155-
KeyRing createdKeyRing =
156-
client.createKeyRing(
157-
CreateKeyRingRequest.newBuilder()
158-
.setParent(locationName.toString())
159-
.setKeyRing(keyRing)
160-
.setKeyRingId(KEY_RING_ID)
161-
.build());
162-
System.out.printf("Created key ring: %s%n", createdKeyRing.getName());
163-
}
145+
// Wait for the specified amount of time.
146+
public static void sleep(int seconds) throws InterruptedException {
147+
TimeUnit.SECONDS.sleep(seconds);
164148
}
165149

166-
// Create a new asymmetric key for the purpose of signing and verifying data.
167-
public static void createAsymmetricSignKey() throws IOException {
168-
// Initialize client that will be used to send requests. This client only
169-
// needs to be created once, and can be reused for multiple requests. After
170-
// completing all of your requests, call the "close" method on the client to
171-
// safely clean up any remaining background resources.
172-
try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
173-
// Build the parent name from the project, location, and key ring.
174-
KeyRingName keyRingName = KeyRingName.of(PROJECT_ID, KMS_LOCATION, KEY_RING_ID);
175-
176-
// Build the asymmetric key to create.
177-
CryptoKey key =
178-
CryptoKey.newBuilder()
179-
.setPurpose(CryptoKeyPurpose.ASYMMETRIC_SIGN)
180-
.setVersionTemplate(
181-
CryptoKeyVersionTemplate.newBuilder()
182-
.setAlgorithm(CryptoKeyVersionAlgorithm.RSA_SIGN_PKCS1_2048_SHA256))
183-
.build();
184-
185-
// Create the key.
186-
CryptoKey createdKey = client.createCryptoKey(keyRingName, KEY_ID, key);
187-
System.out.printf("Created asymmetric key: %s%n", createdKey.getName());
188-
}
189-
}
150+
// Create an asymmetric key pair to be used in certificate signing.
151+
public static KeyPair createAsymmetricKeyPair()
152+
throws NoSuchAlgorithmException, NoSuchProviderException {
153+
Security.addProvider(new BouncyCastleProvider());
190154

191-
public static void cleanupCertificateSignKey() throws IOException, InterruptedException {
192-
try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
193-
CryptoKeyVersionName cryptoKeyVersionName =
194-
CryptoKeyVersionName.of(PROJECT_ID, KMS_LOCATION, KEY_RING_ID, KEY_ID, VERSION_ID);
195-
// Destroy the crypto key version.
196-
CryptoKeyVersion cryptoKeyVersion = client.destroyCryptoKeyVersion(cryptoKeyVersionName);
197-
sleep(5);
198-
// If the response has destroy time, then the version is successfully destroyed.
199-
Assert.assertTrue(cryptoKeyVersion.hasDestroyTime());
200-
}
155+
// Generate the key pair with RSA algorithm using Bouncy Castle (BC).
156+
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
157+
generator.initialize(KEY_SIZE);
158+
KeyPair keyPair = generator.generateKeyPair();
159+
160+
return keyPair;
201161
}
202162

203-
// Wait for the specified amount of time.
204-
public static void sleep(int seconds) throws InterruptedException {
205-
TimeUnit.SECONDS.sleep(seconds);
163+
// Convert the encoded PemObject to ByteString.
164+
public static ByteString convertToPemEncodedByteString(PemObject pemEncodedKey)
165+
throws IOException {
166+
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
167+
PemWriter pemWriter = new PemWriter(new OutputStreamWriter(byteArrayOutputStream));
168+
pemWriter.writeObject(pemEncodedKey);
169+
pemWriter.close();
170+
ByteString keyByteString = ByteString.copyFrom(byteArrayOutputStream.toByteArray());
171+
172+
return keyByteString;
206173
}
207174

208175
@Before

privateca/pom.xml

+5-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@
5454
<artifactId>google-cloud-security-private-ca</artifactId>
5555
<version>1.1.0</version>
5656
</dependency>
57-
57+
<dependency>
58+
<groupId>org.bouncycastle</groupId>
59+
<artifactId>bcpkix-jdk15on</artifactId>
60+
<version>1.58</version>
61+
</dependency>
5862
<dependency>
5963
<groupId>com.google.cloud</groupId>
6064
<artifactId>google-cloud-kms</artifactId>

0 commit comments

Comments
 (0)