18
18
import static com .google .common .truth .Truth .assertThat ;
19
19
import static com .google .common .truth .Truth .assertWithMessage ;
20
20
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 ;
32
21
import com .google .cloud .security .privateca .v1 .CaPoolName ;
33
22
import com .google .cloud .security .privateca .v1 .Certificate ;
34
23
import com .google .cloud .security .privateca .v1 .CertificateAuthority ;
38
27
import com .google .protobuf .ByteString ;
39
28
import java .io .ByteArrayOutputStream ;
40
29
import java .io .IOException ;
30
+ import java .io .OutputStreamWriter ;
41
31
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 ;
42
39
import java .util .UUID ;
43
40
import java .util .concurrent .ExecutionException ;
44
41
import java .util .concurrent .TimeUnit ;
45
42
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 ;
46
46
import org .junit .After ;
47
47
import org .junit .AfterClass ;
48
48
import org .junit .Assert ;
@@ -57,15 +57,12 @@ public class SnippetsIT {
57
57
58
58
private static final String PROJECT_ID = System .getenv ("GOOGLE_CLOUD_PROJECT" );
59
59
private static String LOCATION ;
60
- private static String KMS_LOCATION ;
61
60
private static String CA_POOL_NAME ;
62
61
private static String CA_POOL_NAME_DELETE ;
63
62
private static String CA_NAME ;
64
63
private static String CA_NAME_DELETE ;
65
64
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 ;
69
66
70
67
private ByteArrayOutputStream stdOut ;
71
68
@@ -77,24 +74,24 @@ public static void reqEnvVar(String envVarName) {
77
74
}
78
75
79
76
@ BeforeClass
80
- public static void setUp () throws InterruptedException , ExecutionException , IOException {
77
+ public static void setUp ()
78
+ throws IOException , ExecutionException , NoSuchProviderException , NoSuchAlgorithmException ,
79
+ InterruptedException {
81
80
reqEnvVar ("GOOGLE_APPLICATION_CREDENTIALS" );
82
81
reqEnvVar ("GOOGLE_CLOUD_PROJECT" );
83
82
84
83
LOCATION = "asia-south1" ;
85
- KMS_LOCATION = "global" ;
86
84
CA_POOL_NAME = "ca-pool-" + UUID .randomUUID ().toString ();
87
85
CA_POOL_NAME_DELETE = "ca-pool-" + UUID .randomUUID ().toString ();
88
86
CA_NAME = "ca-name-" + UUID .randomUUID ().toString ();
89
87
CA_NAME_DELETE = "ca-name-" + UUID .randomUUID ().toString ();
90
88
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
94
90
95
91
// Create CA Pool.
96
92
privateca .CreateCaPool .createCaPool (PROJECT_ID , LOCATION , CA_POOL_NAME );
97
93
privateca .CreateCaPool .createCaPool (PROJECT_ID , LOCATION , CA_POOL_NAME_DELETE );
94
+ sleep (5 );
98
95
99
96
// Create and Enable Certificate Authorities.
100
97
privateca .CreateCertificateAuthority .createCertificateAuthority (
@@ -105,17 +102,27 @@ public static void setUp() throws InterruptedException, ExecutionException, IOEx
105
102
privateca .EnableCertificateAuthority .enableCertificateAuthority (
106
103
PROJECT_ID , LOCATION , CA_POOL_NAME , CA_NAME );
107
104
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 );
112
118
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.
117
124
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 );
119
126
sleep (5 );
120
127
}
121
128
@@ -125,9 +132,6 @@ public static void cleanUp() throws InterruptedException, ExecutionException, IO
125
132
ByteArrayOutputStream stdOut = new ByteArrayOutputStream ();
126
133
System .setOut (new PrintStream (stdOut ));
127
134
128
- // De-provision public key.
129
- cleanupCertificateSignKey ();
130
-
131
135
// Delete CA and CA pool.
132
136
privateca .DeleteCertificateAuthority .deleteCertificateAuthority (
133
137
PROJECT_ID , LOCATION , CA_POOL_NAME , CA_NAME );
@@ -138,71 +142,34 @@ public static void cleanUp() throws InterruptedException, ExecutionException, IO
138
142
System .setOut (null );
139
143
}
140
144
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 );
164
148
}
165
149
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 ());
190
154
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 ;
201
161
}
202
162
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 ;
206
173
}
207
174
208
175
@ Before
0 commit comments