Skip to content

Commit 7cd3a07

Browse files
committed
Add Java docs samples for KMS key import.
1 parent 6161d0f commit 7cd3a07

File tree

7 files changed

+482
-90
lines changed

7 files changed

+482
-90
lines changed

kms/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
<groupId>com.google.cloud</groupId>
4343
<artifactId>google-cloud-kms</artifactId>
4444
</dependency>
45+
<dependency>
46+
<groupId>com.google.crypto.tink</groupId>
47+
<artifactId>tink</artifactId>
48+
<version>1.7.0</version>
49+
</dependency>
4550
<!-- [START_EXCLUDE] -->
4651
<dependency>
4752
<groupId>com.google.protobuf</groupId>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kms;
18+
19+
// [START kms_check_state_import_job]
20+
import com.google.cloud.kms.v1.ImportJob;
21+
import com.google.cloud.kms.v1.ImportJobName;
22+
import com.google.cloud.kms.v1.KeyManagementServiceClient;
23+
import java.io.IOException;
24+
25+
public class CheckStateImportJob {
26+
27+
public void checkStateImportJob() throws IOException {
28+
// TODO(developer): Replace these variables before running the sample.
29+
String projectId = "your-project-id";
30+
String locationId = "us-east1";
31+
String keyRingId = "my-key-ring";
32+
String importJobId = "my-import-job";
33+
checkStateImportJob(projectId, locationId, keyRingId, importJobId);
34+
}
35+
36+
// Check the state of an import job in Cloud KMS.
37+
public void checkStateImportJob(String projectId, String locationId,
38+
String keyRingId, String importJobId)
39+
throws IOException {
40+
// Initialize client that will be used to send requests. This client only
41+
// needs to be created once, and can be reused for multiple requests. After
42+
// completing all of your requests, call the "close" method on the client to
43+
// safely clean up any remaining background resources.
44+
try (KeyManagementServiceClient client =
45+
KeyManagementServiceClient.create()) {
46+
// Build the parent name from the project, location, and key ring.
47+
ImportJobName importJobName =
48+
ImportJobName.of(projectId, locationId, keyRingId, importJobId);
49+
50+
// Retrieve the state of an existing import job.
51+
ImportJob importJob = client.getImportJob(importJobName);
52+
System.out.printf("Current state of import job %s: %s%n",
53+
importJob.getName(), importJob.getState());
54+
}
55+
}
56+
}
57+
// [END kms_check_state_import_job]
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kms;
18+
19+
// [START kms_check_state_imported_key]
20+
import com.google.cloud.kms.v1.CryptoKeyVersion;
21+
import com.google.cloud.kms.v1.CryptoKeyVersionName;
22+
import com.google.cloud.kms.v1.KeyManagementServiceClient;
23+
import java.io.IOException;
24+
25+
public class CheckStateImportedKey {
26+
27+
public void checkStateImportedKey() throws IOException {
28+
// TODO(developer): Replace these variables before running the sample.
29+
String projectId = "your-project-id";
30+
String locationId = "us-east1";
31+
String keyRingId = "my-key-ring";
32+
String cryptoKeyId = "my-crypto-key";
33+
String cryptoKeyVersionId = "1";
34+
checkStateImportedKey(projectId, locationId, keyRingId, cryptoKeyId,
35+
cryptoKeyVersionId);
36+
}
37+
38+
// Check the state of an imported key in Cloud KMS.
39+
public void checkStateImportedKey(String projectId, String locationId,
40+
String keyRingId, String cryptoKeyId,
41+
String cryptoKeyVersionId)
42+
throws IOException {
43+
// Initialize client that will be used to send requests. This client only
44+
// needs to be created once, and can be reused for multiple requests. After
45+
// completing all of your requests, call the "close" method on the client to
46+
// safely clean up any remaining background resources.
47+
try (KeyManagementServiceClient client =
48+
KeyManagementServiceClient.create()) {
49+
// Build the version name from its path components.
50+
CryptoKeyVersionName versionName = CryptoKeyVersionName.of(
51+
projectId, locationId, keyRingId, cryptoKeyId, cryptoKeyVersionId);
52+
53+
// Retrieve the state of an existing version.
54+
CryptoKeyVersion version = client.getCryptoKeyVersion(versionName);
55+
System.out.printf("Current state of crypto key version %s: %s%n",
56+
version.getName(), version.getState());
57+
}
58+
}
59+
}
60+
// [END kms_check_state_imported_key]
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kms;
18+
19+
// [START kms_create_import_job]
20+
import com.google.cloud.kms.v1.ImportJob;
21+
import com.google.cloud.kms.v1.KeyManagementServiceClient;
22+
import com.google.cloud.kms.v1.KeyRingName;
23+
import com.google.cloud.kms.v1.ProtectionLevel;
24+
import com.google.cloud.kms.v1.ImportJob.ImportMethod;
25+
26+
import java.io.IOException;
27+
28+
public class CreateImportJob {
29+
30+
public void createImportJob() throws IOException {
31+
// TODO(developer): Replace these variables before running the sample.
32+
String projectId = "your-project-id";
33+
String locationId = "us-east1";
34+
String keyRingId = "my-key-ring";
35+
String id = "my-import-job";
36+
createImportJob(projectId, locationId, keyRingId, id);
37+
}
38+
39+
// Create a new import job.
40+
public void createImportJob(String projectId, String locationId,
41+
String keyRingId, String id) throws IOException {
42+
// Initialize client that will be used to send requests. This client only
43+
// needs to be created once, and can be reused for multiple requests. After
44+
// completing all of your requests, call the "close" method on the client to
45+
// safely clean up any remaining background resources.
46+
try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
47+
// Build the parent name from the project, location, and key ring.
48+
KeyRingName keyRingName = KeyRingName.of(projectId, locationId, keyRingId);
49+
50+
// Build the import job to create, with parameters.
51+
ImportJob importJob = ImportJob
52+
.newBuilder()
53+
// See allowed values and their descriptions at
54+
// https://cloud.google.com/kms/docs/algorithms#protection_levels
55+
.setProtectionLevel(ProtectionLevel.HSM)
56+
// See allowed values and their descriptions at
57+
// https://cloud.google.com/kms/docs/key-wrapping#import_methods
58+
.setImportMethod(ImportMethod.RSA_OAEP_3072_SHA1_AES_256)
59+
.build();
60+
61+
// Create the import job.
62+
ImportJob createdImportJob = client.createImportJob(keyRingName, id, importJob);
63+
System.out.printf("Created import job %s%n", createdImportJob.getName());
64+
}
65+
}
66+
}
67+
// [END kms_create_import_job]
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kms;
18+
19+
// [START kms_create_key_for_import]
20+
import com.google.cloud.kms.v1.CreateCryptoKeyRequest;
21+
import com.google.cloud.kms.v1.CryptoKey;
22+
import com.google.cloud.kms.v1.CryptoKeyVersionTemplate;
23+
import com.google.cloud.kms.v1.KeyManagementServiceClient;
24+
import com.google.cloud.kms.v1.KeyRingName;
25+
import com.google.cloud.kms.v1.ProtectionLevel;
26+
import com.google.cloud.kms.v1.CryptoKey.CryptoKeyPurpose;
27+
import com.google.cloud.kms.v1.CryptoKeyVersion.CryptoKeyVersionAlgorithm;
28+
29+
import java.io.IOException;
30+
31+
public class CreateKeyForImport {
32+
33+
public void createKeyForImport() throws IOException {
34+
// TODO(developer): Replace these variables before running the sample.
35+
String projectId = "your-project-id";
36+
String locationId = "us-east1";
37+
String keyRingId = "my-key-ring";
38+
String id = "my-import-key";
39+
createKeyForImport(projectId, locationId, keyRingId, id);
40+
}
41+
42+
// Create a new crypto key to hold imported key versions.
43+
public void createKeyForImport(String projectId, String locationId,
44+
String keyRingId, String id)
45+
throws IOException {
46+
// Initialize client that will be used to send requests. This client only
47+
// needs to be created once, and can be reused for multiple requests. After
48+
// completing all of your requests, call the "close" method on the client to
49+
// safely clean up any remaining background resources.
50+
try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
51+
// Build the parent name from the project, location, and key ring.
52+
KeyRingName keyRingName = KeyRingName.of(projectId, locationId, keyRingId);
53+
54+
// Create the crypto key.
55+
CryptoKey createdKey = client.createCryptoKey(
56+
CreateCryptoKeyRequest.newBuilder()
57+
.setParent(keyRingName.toString())
58+
.setCryptoKeyId(id)
59+
.setCryptoKey(CryptoKey.newBuilder()
60+
.setPurpose(CryptoKeyPurpose.ASYMMETRIC_SIGN)
61+
.setVersionTemplate(
62+
CryptoKeyVersionTemplate.newBuilder()
63+
.setProtectionLevel(ProtectionLevel.HSM)
64+
.setAlgorithm(CryptoKeyVersionAlgorithm.EC_SIGN_P256_SHA256))
65+
// Ensure that only imported versions may be
66+
// added to this key.
67+
.setImportOnly(true))
68+
.setSkipInitialVersionCreation(true)
69+
.build());
70+
71+
System.out.printf("Created crypto key %s%n", createdKey.getName());
72+
}
73+
}
74+
}
75+
// [END kms_create_crypto_key]
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kms;
18+
19+
// [START kms_import_manually_wrapped_key]
20+
import com.google.cloud.kms.v1.CryptoKeyName;
21+
import com.google.cloud.kms.v1.CryptoKeyVersion;
22+
import com.google.cloud.kms.v1.ImportCryptoKeyVersionRequest;
23+
import com.google.cloud.kms.v1.ImportJob;
24+
import com.google.cloud.kms.v1.ImportJobName;
25+
import com.google.cloud.kms.v1.KeyManagementServiceClient;
26+
import com.google.crypto.tink.subtle.Kwp;
27+
import com.google.protobuf.ByteString;
28+
29+
import java.io.IOException;
30+
import java.security.GeneralSecurityException;
31+
import java.security.KeyFactory;
32+
import java.security.KeyPair;
33+
import java.security.KeyPairGenerator;
34+
import java.security.PublicKey;
35+
import java.security.SecureRandom;
36+
import java.security.spec.ECGenParameterSpec;
37+
import java.security.spec.MGF1ParameterSpec;
38+
import java.security.spec.X509EncodedKeySpec;
39+
import java.util.Arrays;
40+
import java.util.Base64;
41+
42+
import javax.crypto.Cipher;
43+
import javax.crypto.spec.OAEPParameterSpec;
44+
import javax.crypto.spec.PSource;
45+
46+
public class ImportManuallyWrappedKey {
47+
48+
public void importManuallyWrappedKey() throws GeneralSecurityException, IOException {
49+
// TODO(developer): Replace these variables before running the sample.
50+
String projectId = "your-project-id";
51+
String locationId = "us-east1";
52+
String keyRingId = "my-key-ring";
53+
String cryptoKeyId = "my-crypto-key";
54+
String importJobId = "my-import-job";
55+
importManuallyWrappedKey(projectId, locationId, keyRingId, cryptoKeyId,
56+
importJobId);
57+
}
58+
59+
// Generates and imports local key material into Cloud KMS.
60+
public void importManuallyWrappedKey(String projectId, String locationId,
61+
String keyRingId, String cryptoKeyId,
62+
String importJobId) throws GeneralSecurityException, IOException {
63+
64+
// Generate a new ECDSA keypair, and format the private key as PKCS #8 DER.
65+
KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
66+
generator.initialize(new ECGenParameterSpec("secp256r1"));
67+
KeyPair kp = generator.generateKeyPair();
68+
byte[] privateBytes = kp.getPrivate().getEncoded();
69+
70+
// Initialize client that will be used to send requests. This client only
71+
// needs to be created once, and can be reused for multiple requests. After
72+
// completing all of your requests, call the "close" method on the client to
73+
// safely clean up any remaining background resources.
74+
try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
75+
// Build the crypto key and import job names from the project, location,
76+
// key ring, and ID.
77+
CryptoKeyName cryptoKeyName = CryptoKeyName.of(projectId, locationId, keyRingId, cryptoKeyId);
78+
ImportJobName importJobName = ImportJobName.of(projectId, locationId, keyRingId, importJobId);
79+
80+
// Generate a temporary 32-byte key for AES-KWP and wrap the key material.
81+
byte[] kwpKey = new byte[32];
82+
new SecureRandom().nextBytes(kwpKey);
83+
Kwp kwp = new Kwp(kwpKey);
84+
byte[] wrappedTargetKey = kwp.wrap(privateBytes);
85+
86+
// Retrieve the public key from the import job.
87+
ImportJob importJob = client.getImportJob(importJobName);
88+
String publicKeyStr = importJob.getPublicKey().getPem();
89+
// Manually convert PEM to DER. :-(
90+
publicKeyStr = publicKeyStr.replace("-----BEGIN PUBLIC KEY-----", "");
91+
publicKeyStr = publicKeyStr.replace("-----END PUBLIC KEY-----", "");
92+
publicKeyStr = publicKeyStr.replaceAll("\n", "");
93+
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
94+
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(
95+
new X509EncodedKeySpec(publicKeyBytes));
96+
97+
// Wrap the KWP key using the import job key.
98+
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
99+
cipher.init(Cipher.ENCRYPT_MODE, publicKey,
100+
new OAEPParameterSpec("SHA-1", "MGF1",
101+
MGF1ParameterSpec.SHA1,
102+
PSource.PSpecified.DEFAULT));
103+
byte[] wrappedWrappingKey = cipher.doFinal(kwpKey);
104+
105+
// Concatenate the wrapped KWP key and the wrapped target key.
106+
ByteString combinedWrappedKeys = ByteString.copyFrom(wrappedWrappingKey)
107+
.concat(ByteString.copyFrom(wrappedTargetKey));
108+
109+
// Import the wrapped key material.
110+
CryptoKeyVersion version = client.importCryptoKeyVersion(
111+
ImportCryptoKeyVersionRequest.newBuilder()
112+
.setParent(cryptoKeyName.toString())
113+
.setImportJob(importJobName.toString())
114+
.setAlgorithm(CryptoKeyVersion.CryptoKeyVersionAlgorithm.EC_SIGN_P256_SHA256)
115+
.setRsaAesWrappedKey(combinedWrappedKeys)
116+
.build());
117+
118+
System.out.printf("Imported: %s%n", version.getName());
119+
}
120+
}
121+
}
122+
// [END kms_import_manually_wrapped_key]

0 commit comments

Comments
 (0)