Skip to content

Commit a668527

Browse files
committed
Use key provider id to namespace S3 keyring(s).
1 parent 9e8a777 commit a668527

File tree

8 files changed

+128
-68
lines changed

8 files changed

+128
-68
lines changed

src/main/java/software/amazon/encryption/s3/internal/S3ObjectMetadataStrategy.java

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import software.amazon.encryption.s3.algorithms.AlgorithmSuite;
1616
import software.amazon.encryption.s3.materials.EncryptedDataKey;
1717
import software.amazon.encryption.s3.materials.EncryptionMaterials;
18+
import software.amazon.encryption.s3.materials.S3Keyring;
1819

1920
/**
2021
* This stores encryption metadata in the S3 object metadata.
@@ -43,7 +44,7 @@ public PutObjectRequest encodeMetadata(
4344
metadata.put(MetadataKey.CONTENT_NONCE, _encoder.encodeToString(encryptedContent.nonce));
4445
metadata.put(MetadataKey.CONTENT_CIPHER, materials.algorithmSuite().cipherName());
4546
metadata.put(MetadataKey.CONTENT_CIPHER_TAG_LENGTH, Integer.toString(materials.algorithmSuite().cipherTagLengthBits()));
46-
metadata.put(MetadataKey.ENCRYPTED_DATA_KEY_ALGORITHM, edk.keyProviderId());
47+
metadata.put(MetadataKey.ENCRYPTED_DATA_KEY_ALGORITHM, new String(edk.keyProviderInfo(), StandardCharsets.UTF_8));
4748

4849
try (JsonWriter jsonWriter = JsonWriter.create()) {
4950
jsonWriter.writeStartObject();
@@ -61,32 +62,6 @@ public PutObjectRequest encodeMetadata(
6162
return request.toBuilder().metadata(metadata).build();
6263
}
6364

64-
public PutObjectRequest encodeMetadata(ContentMetadata contentMetadata, PutObjectRequest request) {
65-
Map<String,String> requestMetadata = new HashMap<>(request.metadata());
66-
EncryptedDataKey edk = contentMetadata.encryptedDataKey();
67-
requestMetadata.put(MetadataKey.ENCRYPTED_DATA_KEY_V2, _encoder.encodeToString(edk.ciphertext()));
68-
requestMetadata.put(MetadataKey.CONTENT_NONCE, _encoder.encodeToString(
69-
contentMetadata.contentNonce()));
70-
requestMetadata.put(MetadataKey.CONTENT_CIPHER, contentMetadata.algorithmSuite().cipherName());
71-
requestMetadata.put(MetadataKey.CONTENT_CIPHER_TAG_LENGTH, Integer.toString(contentMetadata.algorithmSuite().cipherTagLengthBits()));
72-
requestMetadata.put(MetadataKey.ENCRYPTED_DATA_KEY_ALGORITHM, edk.keyProviderId());
73-
74-
try (JsonWriter jsonWriter = JsonWriter.create()) {
75-
jsonWriter.writeStartObject();
76-
for (Entry<String,String> entry : contentMetadata.encryptedDataKeyContext().entrySet()) {
77-
jsonWriter.writeFieldName(entry.getKey()).writeValue(entry.getValue());
78-
}
79-
jsonWriter.writeEndObject();
80-
81-
String jsonEncryptionContext = new String(jsonWriter.getBytes(), StandardCharsets.UTF_8);
82-
requestMetadata.put(MetadataKey.ENCRYPTED_DATA_KEY_CONTEXT, jsonEncryptionContext);
83-
} catch (JsonGenerationException e) {
84-
throw new S3EncryptionClientException("Cannot serialize encryption context to JSON.", e);
85-
}
86-
87-
return request.toBuilder().metadata(requestMetadata).build();
88-
}
89-
9065
@Override
9166
public ContentMetadata decodeMetadata(GetObjectResponse response) {
9267
Map<String, String> metadata = response.metadata();
@@ -106,14 +81,18 @@ public ContentMetadata decodeMetadata(GetObjectResponse response) {
10681

10782
// Do algorithm suite dependent decoding
10883
byte[] edkCiphertext;
109-
String keyProviderId;
84+
85+
// Currently, this is not stored within the metadata,
86+
// signal to keyring(s) intended for S3EC
87+
final String keyProviderId = S3Keyring.KEY_PROVIDER_ID;
88+
String keyProviderInfo;
11089
switch (algorithmSuite) {
11190
case ALG_AES_256_CBC_IV16_NO_KDF:
11291
// Extract encrypted data key ciphertext
11392
edkCiphertext = _decoder.decode(metadata.get(MetadataKey.ENCRYPTED_DATA_KEY_V1));
11493

11594
// Hardcode the key provider id to match what V1 does
116-
keyProviderId = "AES";
95+
keyProviderInfo = "AES";
11796

11897
break;
11998
case ALG_AES_256_GCM_IV12_TAG16_NO_KDF:
@@ -127,7 +106,7 @@ public ContentMetadata decodeMetadata(GetObjectResponse response) {
127106

128107
// Extract encrypted data key ciphertext and provider id
129108
edkCiphertext = _decoder.decode(metadata.get(MetadataKey.ENCRYPTED_DATA_KEY_V2));
130-
keyProviderId = metadata.get(MetadataKey.ENCRYPTED_DATA_KEY_ALGORITHM);
109+
keyProviderInfo = metadata.get(MetadataKey.ENCRYPTED_DATA_KEY_ALGORITHM);
131110

132111
break;
133112
default:
@@ -139,6 +118,7 @@ public ContentMetadata decodeMetadata(GetObjectResponse response) {
139118
EncryptedDataKey edk = EncryptedDataKey.builder()
140119
.ciphertext(edkCiphertext)
141120
.keyProviderId(keyProviderId)
121+
.keyProviderInfo(keyProviderInfo.getBytes(StandardCharsets.UTF_8))
142122
.build();
143123

144124
// Get encrypted data key encryption context

src/main/java/software/amazon/encryption/s3/materials/AesKeyring.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class AesKeyring extends S3Keyring {
2424

2525
private final DecryptDataKeyStrategy _aesStrategy = new DecryptDataKeyStrategy() {
2626

27-
private static final String KEY_PROVIDER_ID = "AES";
27+
private static final String KEY_PROVIDER_INFO = "AES";
2828
private static final String CIPHER_ALGORITHM = "AES";
2929

3030
@Override
@@ -33,8 +33,8 @@ public boolean isLegacy() {
3333
}
3434

3535
@Override
36-
public String keyProviderId() {
37-
return KEY_PROVIDER_ID;
36+
public String keyProviderInfo() {
37+
return KEY_PROVIDER_INFO;
3838
}
3939

4040
@Override
@@ -48,7 +48,7 @@ public byte[] decryptDataKey(DecryptionMaterials materials, EncryptedDataKey enc
4848

4949
private final DecryptDataKeyStrategy _aesWrapStrategy = new DecryptDataKeyStrategy() {
5050

51-
private static final String KEY_PROVIDER_ID = "AESWrap";
51+
private static final String KEY_PROVIDER_INFO = "AESWrap";
5252
private static final String CIPHER_ALGORITHM = "AESWrap";
5353

5454
@Override
@@ -57,8 +57,8 @@ public boolean isLegacy() {
5757
}
5858

5959
@Override
60-
public String keyProviderId() {
61-
return KEY_PROVIDER_ID;
60+
public String keyProviderInfo() {
61+
return KEY_PROVIDER_INFO;
6262
}
6363

6464
@Override
@@ -73,7 +73,7 @@ public byte[] decryptDataKey(DecryptionMaterials materials, EncryptedDataKey enc
7373

7474
private final DataKeyStrategy _aesGcmStrategy = new DataKeyStrategy() {
7575

76-
private static final String KEY_PROVIDER_ID = "AES/GCM";
76+
private static final String KEY_PROVIDER_INFO = "AES/GCM";
7777
private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
7878
private static final int NONCE_LENGTH_BYTES = 12;
7979
private static final int TAG_LENGTH_BYTES = 16;
@@ -85,8 +85,8 @@ public boolean isLegacy() {
8585
}
8686

8787
@Override
88-
public String keyProviderId() {
89-
return KEY_PROVIDER_ID;
88+
public String keyProviderInfo() {
89+
return KEY_PROVIDER_INFO;
9090
}
9191

9292
@Override
@@ -138,9 +138,9 @@ private AesKeyring(Builder builder) {
138138

139139
_wrappingKey = builder._wrappingKey;
140140

141-
decryptStrategies.put(_aesStrategy.keyProviderId(), _aesStrategy);
142-
decryptStrategies.put(_aesWrapStrategy.keyProviderId(), _aesWrapStrategy);
143-
decryptStrategies.put(_aesGcmStrategy.keyProviderId(), _aesGcmStrategy);
141+
decryptStrategies.put(_aesStrategy.keyProviderInfo(), _aesStrategy);
142+
decryptStrategies.put(_aesWrapStrategy.keyProviderInfo(), _aesWrapStrategy);
143+
decryptStrategies.put(_aesGcmStrategy.keyProviderInfo(), _aesGcmStrategy);
144144
}
145145

146146
public static Builder builder() {

src/main/java/software/amazon/encryption/s3/materials/DecryptDataKeyStrategy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
public interface DecryptDataKeyStrategy {
66
boolean isLegacy();
77

8-
String keyProviderId();
8+
String keyProviderInfo();
99

1010
byte[] decryptDataKey(DecryptionMaterials materials, EncryptedDataKey encryptedDataKey)
1111
throws GeneralSecurityException;

src/main/java/software/amazon/encryption/s3/materials/EncryptDataKeyStrategy.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
import java.security.GeneralSecurityException;
44
import java.security.SecureRandom;
5-
import java.util.Map;
65

76
public interface EncryptDataKeyStrategy {
8-
String keyProviderId();
7+
String keyProviderInfo();
98

109
default EncryptionMaterials modifyMaterials(EncryptionMaterials materials) {
1110
return materials;

src/main/java/software/amazon/encryption/s3/materials/KmsKeyring.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package software.amazon.encryption.s3.materials;
22

33
import java.security.SecureRandom;
4-
import java.util.Collections;
54
import java.util.HashMap;
65
import java.util.Map;
76
import java.util.TreeMap;
@@ -28,16 +27,16 @@ public class KmsKeyring extends S3Keyring {
2827

2928
private final DecryptDataKeyStrategy _kmsStrategy = new DecryptDataKeyStrategy() {
3029

31-
private static final String KEY_PROVIDER_ID = "kms";
30+
private static final String KEY_PROVIDER_INFO = "kms";
3231

3332
@Override
3433
public boolean isLegacy() {
3534
return true;
3635
}
3736

3837
@Override
39-
public String keyProviderId() {
40-
return KEY_PROVIDER_ID;
38+
public String keyProviderInfo() {
39+
return KEY_PROVIDER_INFO;
4140
}
4241

4342
@Override
@@ -56,7 +55,7 @@ public byte[] decryptDataKey(DecryptionMaterials materials, EncryptedDataKey enc
5655

5756
private final DataKeyStrategy _kmsContextStrategy = new DataKeyStrategy() {
5857

59-
private static final String KEY_PROVIDER_ID = "kms+context";
58+
private static final String KEY_PROVIDER_INFO = "kms+context";
6059
private static final String ENCRYPTION_CONTEXT_ALGORITHM_KEY = "aws:x-amz-cek-alg";
6160

6261
@Override
@@ -65,8 +64,8 @@ public boolean isLegacy() {
6564
}
6665

6766
@Override
68-
public String keyProviderId() {
69-
return KEY_PROVIDER_ID;
67+
public String keyProviderInfo() {
68+
return KEY_PROVIDER_INFO;
7069
}
7170

7271
@Override
@@ -121,8 +120,8 @@ public KmsKeyring(Builder builder) {
121120
_kmsClient = builder._kmsClient;
122121
_wrappingKeyId = builder._wrappingKeyId;
123122

124-
decryptStrategies.put(_kmsStrategy.keyProviderId(), _kmsStrategy);
125-
decryptStrategies.put(_kmsContextStrategy.keyProviderId(), _kmsContextStrategy);
123+
decryptStrategies.put(_kmsStrategy.keyProviderInfo(), _kmsStrategy);
124+
decryptStrategies.put(_kmsContextStrategy.keyProviderInfo(), _kmsContextStrategy);
126125
}
127126

128127
public static Builder builder() {

src/main/java/software/amazon/encryption/s3/materials/RsaKeyring.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class RsaKeyring extends S3Keyring {
2626
private final KeyPair _wrappingKeyPair;
2727

2828
private final DecryptDataKeyStrategy _rsaEcbStrategy = new DecryptDataKeyStrategy() {
29-
private static final String KEY_PROVIDER_ID = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
29+
private static final String KEY_PROVIDER_INFO = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
3030
private static final String CIPHER_ALGORITHM = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
3131

3232
@Override
@@ -35,8 +35,8 @@ public boolean isLegacy() {
3535
}
3636

3737
@Override
38-
public String keyProviderId() {
39-
return KEY_PROVIDER_ID;
38+
public String keyProviderInfo() {
39+
return KEY_PROVIDER_INFO;
4040
}
4141

4242
@Override
@@ -52,7 +52,7 @@ public byte[] decryptDataKey(DecryptionMaterials materials, EncryptedDataKey enc
5252

5353
private final DataKeyStrategy _rsaOaepStrategy = new DataKeyStrategy() {
5454

55-
private static final String KEY_PROVIDER_ID = "RSA-OAEP-SHA1";
55+
private static final String KEY_PROVIDER_INFO = "RSA-OAEP-SHA1";
5656
private static final String CIPHER_ALGORITHM = "RSA/ECB/OAEPPadding";
5757
private static final String DIGEST_NAME = "SHA-1";
5858
private static final String MGF_NAME = "MGF1";
@@ -68,8 +68,8 @@ public boolean isLegacy() {
6868
}
6969

7070
@Override
71-
public String keyProviderId() {
72-
return KEY_PROVIDER_ID;
71+
public String keyProviderInfo() {
72+
return KEY_PROVIDER_INFO;
7373
}
7474

7575
@Override
@@ -135,8 +135,8 @@ private RsaKeyring(Builder builder) {
135135

136136
_wrappingKeyPair = builder._wrappingKeyPair;
137137

138-
decryptStrategies.put(_rsaEcbStrategy.keyProviderId(), _rsaEcbStrategy);
139-
decryptStrategies.put(_rsaOaepStrategy.keyProviderId(), _rsaOaepStrategy);
138+
decryptStrategies.put(_rsaEcbStrategy.keyProviderInfo(), _rsaEcbStrategy);
139+
decryptStrategies.put(_rsaOaepStrategy.keyProviderInfo(), _rsaOaepStrategy);
140140
}
141141

142142
public static Builder builder() {

src/main/java/software/amazon/encryption/s3/materials/S3Keyring.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package software.amazon.encryption.s3.materials;
22

3+
import java.nio.charset.StandardCharsets;
34
import java.security.SecureRandom;
45
import java.util.ArrayList;
56
import java.util.List;
@@ -13,6 +14,8 @@
1314
*/
1415
abstract public class S3Keyring implements Keyring {
1516

17+
public static final String KEY_PROVIDER_ID = "S3Keyring";
18+
1619
private final boolean _enableLegacyModes;
1720
private final SecureRandom _secureRandom;
1821
private final DataKeyGenerator _dataKeyGenerator;
@@ -39,7 +42,8 @@ public EncryptionMaterials onEncrypt(EncryptionMaterials materials) {
3942

4043
byte[] ciphertext = encryptStrategy.encryptDataKey(_secureRandom, materials);
4144
EncryptedDataKey encryptedDataKey = EncryptedDataKey.builder()
42-
.keyProviderId(encryptStrategy.keyProviderId())
45+
.keyProviderId(S3Keyring.KEY_PROVIDER_ID)
46+
.keyProviderInfo(encryptStrategy.keyProviderInfo().getBytes(StandardCharsets.UTF_8))
4347
.ciphertext(ciphertext)
4448
.build();
4549

@@ -50,7 +54,7 @@ public EncryptionMaterials onEncrypt(EncryptionMaterials materials) {
5054
.encryptedDataKeys(encryptedDataKeys)
5155
.build();
5256
} catch (Exception e) {
53-
throw new S3EncryptionClientException("Unable to " + encryptStrategy.keyProviderId() + " wrap", e);
57+
throw new S3EncryptionClientException("Unable to " + encryptStrategy.keyProviderInfo() + " wrap", e);
5458
}
5559
}
5660

@@ -68,21 +72,26 @@ public DecryptionMaterials onDecrypt(final DecryptionMaterials materials, List<E
6872

6973
EncryptedDataKey encryptedDataKey = encryptedDataKeys.get(0);
7074
final String keyProviderId = encryptedDataKey.keyProviderId();
75+
if (!KEY_PROVIDER_ID.equals(keyProviderId)) {
76+
throw new S3EncryptionClientException("Unknown key provider: " + keyProviderId);
77+
}
78+
79+
String keyProviderInfo = new String(encryptedDataKey.keyProviderInfo(), StandardCharsets.UTF_8);
7180

72-
DecryptDataKeyStrategy decryptStrategy = decryptStrategies().get(keyProviderId);
81+
DecryptDataKeyStrategy decryptStrategy = decryptStrategies().get(keyProviderInfo);
7382
if (decryptStrategy == null) {
74-
throw new S3EncryptionClientException("Unknown key wrap: " + keyProviderId);
83+
throw new S3EncryptionClientException("Unknown key wrap: " + keyProviderInfo);
7584
}
7685

7786
if (decryptStrategy.isLegacy() && !_enableLegacyModes) {
78-
throw new S3EncryptionClientException("Enable legacy modes to use legacy key wrap: " + keyProviderId);
87+
throw new S3EncryptionClientException("Enable legacy modes to use legacy key wrap: " + keyProviderInfo);
7988
}
8089

8190
try {
8291
byte[] plaintext = decryptStrategy.decryptDataKey(materials, encryptedDataKey);
8392
return materials.toBuilder().plaintextDataKey(plaintext).build();
8493
} catch (Exception e) {
85-
throw new S3EncryptionClientException("Unable to " + keyProviderId + " unwrap", e);
94+
throw new S3EncryptionClientException("Unable to " + keyProviderInfo + " unwrap", e);
8695
}
8796
}
8897

0 commit comments

Comments
 (0)