Skip to content

Commit 5e82a7a

Browse files
juergwcopybara-github
authored andcommittedJul 24, 2023
Add a create function to KmsEnvelopeAead.
This function uses the new Parameters instead of the old proto KeyTemplates. PiperOrigin-RevId: 550614620 Change-Id: I88a94202851d1b83aa71e0dcc80981f502ef4f2f
1 parent 61da4aa commit 5e82a7a

File tree

4 files changed

+125
-18
lines changed

4 files changed

+125
-18
lines changed
 

‎src/main/java/com/google/crypto/tink/aead/BUILD.bazel

+6
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,12 @@ java_library(
124124
name = "kms_envelope_aead",
125125
srcs = ["KmsEnvelopeAead.java"],
126126
deps = [
127+
":aead_parameters",
127128
"//proto:tink_java_proto",
128129
"//src/main/java/com/google/crypto/tink:aead",
129130
"//src/main/java/com/google/crypto/tink:registry",
131+
"//src/main/java/com/google/crypto/tink:tink_proto_parameters_format",
132+
"@maven//:com_google_protobuf_protobuf_java",
130133
],
131134
)
132135

@@ -554,9 +557,12 @@ android_library(
554557
name = "kms_envelope_aead-android",
555558
srcs = ["KmsEnvelopeAead.java"],
556559
deps = [
560+
":aead_parameters-android",
557561
"//proto:tink_java_proto_lite",
558562
"//src/main/java/com/google/crypto/tink:aead-android",
559563
"//src/main/java/com/google/crypto/tink:registry-android",
564+
"//src/main/java/com/google/crypto/tink:tink_proto_parameters_format-android",
565+
"@maven//:com_google_protobuf_protobuf_javalite",
560566
],
561567
)
562568

‎src/main/java/com/google/crypto/tink/aead/KmsEnvelopeAead.java

+25
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818

1919
import com.google.crypto.tink.Aead;
2020
import com.google.crypto.tink.Registry;
21+
import com.google.crypto.tink.TinkProtoParametersFormat;
2122
import com.google.crypto.tink.proto.KeyTemplate;
23+
import com.google.protobuf.ExtensionRegistryLite;
24+
import com.google.protobuf.InvalidProtocolBufferException;
2225
import java.nio.BufferUnderflowException;
2326
import java.nio.ByteBuffer;
2427
import java.security.GeneralSecurityException;
@@ -78,6 +81,28 @@ public KmsEnvelopeAead(KeyTemplate dekTemplate, Aead remote) {
7881
this.remote = remote;
7982
}
8083

84+
/**
85+
* Creates a new instance of Tink's KMS Envelope AEAD.
86+
*
87+
* <p>{@code dekParameters} must be any of these Tink AEAD parameters (any other will be
88+
* rejected): {@link AesGcmParameters}, {@link ChaCha20Poly1305Parameters}, {@link
89+
* XChaCha20Poly1305Parameters}, {@link AesCtrHmacAeadParameters}, {@link AesGcmSivParameters}, or
90+
* {@link AesEaxParameters}.
91+
*/
92+
public static Aead create(AeadParameters dekParameters, Aead remote)
93+
throws GeneralSecurityException {
94+
KeyTemplate dekTemplate;
95+
try {
96+
dekTemplate =
97+
KeyTemplate.parseFrom(
98+
TinkProtoParametersFormat.serialize(dekParameters),
99+
ExtensionRegistryLite.getEmptyRegistry());
100+
} catch (InvalidProtocolBufferException e) {
101+
throw new GeneralSecurityException(e);
102+
}
103+
return new KmsEnvelopeAead(dekTemplate, remote);
104+
}
105+
81106
@Override
82107
public byte[] encrypt(final byte[] plaintext, final byte[] associatedData)
83108
throws GeneralSecurityException {

‎src/test/java/com/google/crypto/tink/aead/BUILD.bazel

+8
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,19 @@ java_test(
5454
"//src/main/java/com/google/crypto/tink:aead",
5555
"//src/main/java/com/google/crypto/tink:key_template",
5656
"//src/main/java/com/google/crypto/tink:key_templates",
57+
"//src/main/java/com/google/crypto/tink:kms_client",
58+
"//src/main/java/com/google/crypto/tink:kms_clients",
5759
"//src/main/java/com/google/crypto/tink:registry_cluster",
5860
"//src/main/java/com/google/crypto/tink/aead:aead_config",
61+
"//src/main/java/com/google/crypto/tink/aead:aead_parameters",
62+
"//src/main/java/com/google/crypto/tink/aead:aes_ctr_hmac_aead_key_manager",
5963
"//src/main/java/com/google/crypto/tink/aead:kms_envelope_aead",
64+
"//src/main/java/com/google/crypto/tink/aead:kms_envelope_aead_key_manager",
65+
"//src/main/java/com/google/crypto/tink/aead:predefined_aead_parameters",
6066
"//src/main/java/com/google/crypto/tink/internal:key_template_proto_converter",
6167
"//src/main/java/com/google/crypto/tink/mac:hmac_key_manager",
68+
"//src/main/java/com/google/crypto/tink/subtle:random",
69+
"//src/main/java/com/google/crypto/tink/testing:fake_kms_client",
6270
"@maven//:com_google_truth_truth",
6371
"@maven//:junit_junit",
6472
],

‎src/test/java/com/google/crypto/tink/aead/KmsEnvelopeAeadTest.java

+86-18
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@
2424
import com.google.crypto.tink.KeyTemplate;
2525
import com.google.crypto.tink.KeyTemplates;
2626
import com.google.crypto.tink.KeysetHandle;
27+
import com.google.crypto.tink.KmsClient;
28+
import com.google.crypto.tink.KmsClients;
2729
import com.google.crypto.tink.internal.KeyTemplateProtoConverter;
2830
import com.google.crypto.tink.mac.HmacKeyManager;
31+
import com.google.crypto.tink.subtle.Random;
32+
import com.google.crypto.tink.testing.FakeKmsClient;
2933
import java.security.GeneralSecurityException;
3034
import org.junit.BeforeClass;
3135
import org.junit.Test;
@@ -50,6 +54,33 @@ private Aead generateNewRemoteAead() throws GeneralSecurityException {
5054
return keysetHandle.getPrimitive(Aead.class);
5155
}
5256

57+
@DataPoints("dekParameters")
58+
public static final AeadParameters[] DEK_PARAMETERS =
59+
new AeadParameters[] {
60+
PredefinedAeadParameters.AES128_GCM,
61+
PredefinedAeadParameters.AES256_GCM,
62+
PredefinedAeadParameters.AES128_EAX,
63+
PredefinedAeadParameters.AES256_EAX,
64+
PredefinedAeadParameters.AES128_CTR_HMAC_SHA256,
65+
PredefinedAeadParameters.AES256_CTR_HMAC_SHA256,
66+
PredefinedAeadParameters.CHACHA20_POLY1305,
67+
PredefinedAeadParameters.XCHACHA20_POLY1305,
68+
};
69+
70+
@Theory
71+
public void createEncryptDecrypt_works(
72+
@FromDataPoints("dekParameters") AeadParameters dekParameters) throws Exception {
73+
Aead remoteAead = this.generateNewRemoteAead();
74+
Aead envAead = KmsEnvelopeAead.create(dekParameters, remoteAead);
75+
byte[] plaintext = "plaintext".getBytes(UTF_8);
76+
byte[] associatedData = "associatedData".getBytes(UTF_8);
77+
byte[] ciphertext = envAead.encrypt(plaintext, associatedData);
78+
assertThat(envAead.decrypt(ciphertext, associatedData)).isEqualTo(plaintext);
79+
80+
assertThat(envAead.decrypt(envAead.encrypt(plaintext, EMPTY_ADD), EMPTY_ADD))
81+
.isEqualTo(plaintext);
82+
}
83+
5384
@DataPoints("tinkDekTemplates")
5485
public static final String[] TINK_DEK_TEMPLATES =
5586
new String[] {
@@ -65,10 +96,10 @@ private Aead generateNewRemoteAead() throws GeneralSecurityException {
6596
};
6697

6798
@Theory
68-
public void encryptDecrypt_works(@FromDataPoints("tinkDekTemplates") String dekTemplateName)
69-
throws Exception {
99+
public void legacyConstructorEncryptDecrypt_works(
100+
@FromDataPoints("tinkDekTemplates") String dekTemplateName) throws Exception {
70101
Aead remoteAead = this.generateNewRemoteAead();
71-
KmsEnvelopeAead envAead =
102+
Aead envAead =
72103
new KmsEnvelopeAead(
73104
KeyTemplateProtoConverter.toProto(KeyTemplates.get(dekTemplateName)), remoteAead);
74105
byte[] plaintext = "plaintext".getBytes(UTF_8);
@@ -94,9 +125,7 @@ public void createKeyFormatWithInvalidDekTemplate_fails() throws Exception {
94125
@Test
95126
public void decryptWithInvalidAssociatedData_fails() throws GeneralSecurityException {
96127
Aead remoteAead = this.generateNewRemoteAead();
97-
KmsEnvelopeAead envAead =
98-
new KmsEnvelopeAead(
99-
KeyTemplateProtoConverter.toProto(KeyTemplates.get("AES128_EAX")), remoteAead);
128+
Aead envAead = KmsEnvelopeAead.create(PredefinedAeadParameters.AES128_EAX, remoteAead);
100129
byte[] plaintext = "plaintext".getBytes(UTF_8);
101130
byte[] associatedData = "associatedData".getBytes(UTF_8);
102131
byte[] ciphertext = envAead.encrypt(plaintext, associatedData);
@@ -109,9 +138,7 @@ public void decryptWithInvalidAssociatedData_fails() throws GeneralSecurityExcep
109138
@Test
110139
public void corruptedCiphertext_fails() throws GeneralSecurityException {
111140
Aead remoteAead = this.generateNewRemoteAead();
112-
KmsEnvelopeAead envAead =
113-
new KmsEnvelopeAead(
114-
KeyTemplateProtoConverter.toProto(KeyTemplates.get("AES128_EAX")), remoteAead);
141+
Aead envAead = KmsEnvelopeAead.create(PredefinedAeadParameters.AES128_EAX, remoteAead);
115142
byte[] associatedData = "envelope_ad".getBytes(UTF_8);
116143
byte[] plaintext = "helloworld".getBytes(UTF_8);
117144
byte[] ciphertext = envAead.encrypt(plaintext, associatedData);
@@ -124,9 +151,7 @@ public void corruptedCiphertext_fails() throws GeneralSecurityException {
124151
@Test
125152
public void corruptedDek_fails() throws GeneralSecurityException {
126153
Aead remoteAead = this.generateNewRemoteAead();
127-
KmsEnvelopeAead envAead =
128-
new KmsEnvelopeAead(
129-
KeyTemplateProtoConverter.toProto(KeyTemplates.get("AES128_EAX")), remoteAead);
154+
Aead envAead = KmsEnvelopeAead.create(PredefinedAeadParameters.AES128_EAX, remoteAead);
130155
byte[] plaintext = "helloworld".getBytes(UTF_8);
131156
byte[] associatedData = "envelope_ad".getBytes(UTF_8);
132157
byte[] ciphertext = envAead.encrypt(plaintext, associatedData);
@@ -139,9 +164,7 @@ public void corruptedDek_fails() throws GeneralSecurityException {
139164
@Test
140165
public void ciphertextTooShort_fails() throws GeneralSecurityException {
141166
Aead remoteAead = this.generateNewRemoteAead();
142-
KmsEnvelopeAead envAead =
143-
new KmsEnvelopeAead(
144-
KeyTemplateProtoConverter.toProto(KeyTemplates.get("AES128_EAX")), remoteAead);
167+
Aead envAead = KmsEnvelopeAead.create(PredefinedAeadParameters.AES128_EAX, remoteAead);
145168
assertThrows(
146169
GeneralSecurityException.class,
147170
() -> envAead.decrypt("foo".getBytes(UTF_8), "envelope_ad".getBytes(UTF_8)));
@@ -150,9 +173,7 @@ public void ciphertextTooShort_fails() throws GeneralSecurityException {
150173
@Test
151174
public void malformedDekLength_fails() throws GeneralSecurityException {
152175
Aead remoteAead = this.generateNewRemoteAead();
153-
KmsEnvelopeAead envAead =
154-
new KmsEnvelopeAead(
155-
KeyTemplateProtoConverter.toProto(KeyTemplates.get("AES128_EAX")), remoteAead);
176+
Aead envAead = KmsEnvelopeAead.create(PredefinedAeadParameters.AES128_EAX, remoteAead);
156177

157178
byte[] plaintext = "helloworld".getBytes(UTF_8);
158179
byte[] associatedData = "envelope_ad".getBytes(UTF_8);
@@ -174,6 +195,53 @@ public void malformedDekLength_fails() throws GeneralSecurityException {
174195
GeneralSecurityException.class,
175196
() -> envAead.decrypt(corruptedCiphertext2, associatedData));
176197
}
198+
199+
@Test
200+
public void create_isCompatibleWithOldConstructor() throws Exception {
201+
String kekUri = FakeKmsClient.createFakeKeyUri();
202+
Aead remoteAead = new FakeKmsClient().getAead(kekUri);
203+
204+
Aead aead1 =
205+
new KmsEnvelopeAead(
206+
KeyTemplateProtoConverter.toProto(
207+
AesCtrHmacAeadKeyManager.aes128CtrHmacSha256Template()),
208+
remoteAead);
209+
Aead aead2 =
210+
KmsEnvelopeAead.create(PredefinedAeadParameters.AES128_CTR_HMAC_SHA256, remoteAead);
211+
212+
byte[] plaintext = Random.randBytes(20);
213+
byte[] associatedData = Random.randBytes(20);
214+
assertThat(aead1.decrypt(aead2.encrypt(plaintext, associatedData), associatedData))
215+
.isEqualTo(plaintext);
216+
assertThat(aead2.decrypt(aead1.encrypt(plaintext, associatedData), associatedData))
217+
.isEqualTo(plaintext);
218+
}
219+
220+
@Test
221+
public void create_isCompatibleWithKmsEnvelopeAeadKey() throws Exception {
222+
String kekUri = FakeKmsClient.createFakeKeyUri();
223+
KeyTemplate dekTemplate = AesCtrHmacAeadKeyManager.aes128CtrHmacSha256Template();
224+
225+
// Register kmsClient and create a keyset with a KmsEnvelopeAeadKey key.
226+
KmsClient kmsClient1 = new FakeKmsClient(kekUri);
227+
KmsClients.add(kmsClient1);
228+
KeysetHandle handle1 =
229+
KeysetHandle.generateNew(KmsEnvelopeAeadKeyManager.createKeyTemplate(kekUri, dekTemplate));
230+
Aead aead1 = handle1.getPrimitive(Aead.class);
231+
232+
// Get Aead object from the kmsClient, and create the envelope AEAD without the registry.
233+
Aead remoteAead = new FakeKmsClient().getAead(kekUri);
234+
Aead aead2 =
235+
KmsEnvelopeAead.create(PredefinedAeadParameters.AES128_CTR_HMAC_SHA256, remoteAead);
236+
237+
// Check that aead1 and aead2 implement the same primitive
238+
byte[] plaintext = Random.randBytes(20);
239+
byte[] associatedData = Random.randBytes(20);
240+
assertThat(aead1.decrypt(aead2.encrypt(plaintext, associatedData), associatedData))
241+
.isEqualTo(plaintext);
242+
assertThat(aead2.decrypt(aead1.encrypt(plaintext, associatedData), associatedData))
243+
.isEqualTo(plaintext);
244+
}
177245
}
178246

179247

0 commit comments

Comments
 (0)
Please sign in to comment.