Skip to content

Commit 92df6e9

Browse files
committed
Generate data keys from keyring.
1 parent a196398 commit 92df6e9

File tree

6 files changed

+78
-23
lines changed

6 files changed

+78
-23
lines changed

src/main/java/software/amazon/encryption/s3/S3EncryptionClient.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ public S3EncryptionClient(S3Client client, MaterialsManager materialsManager) {
6262
public PutObjectResponse putObject(PutObjectRequest putObjectRequest, RequestBody requestBody)
6363
throws AwsServiceException, SdkClientException, S3Exception {
6464

65+
// TODO: This is proof-of-concept code and needs to be refactored
66+
6567
// Get content encryption key
6668
EncryptionMaterials materials = _materialsManager.getEncryptionMaterials(EncryptionMaterialsRequest.builder()
6769
.build());
@@ -129,6 +131,9 @@ public PutObjectResponse putObject(PutObjectRequest putObjectRequest, RequestBod
129131
@Override
130132
public <T> T getObject(GetObjectRequest getObjectRequest, ResponseTransformer<GetObjectResponse, T> responseTransformer)
131133
throws NoSuchKeyException, InvalidObjectStateException, AwsServiceException, SdkClientException, S3Exception {
134+
135+
// TODO: This is proof-of-concept code and needs to be refactored
136+
132137
ResponseInputStream<GetObjectResponse> objectStream = _wrappedClient.getObject(getObjectRequest);
133138
byte[] output;
134139
try {

src/main/java/software/amazon/encryption/s3/algorithms/AlgorithmSuite.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ public enum AlgorithmSuite {
3939
this._cipherMaxContentLengthBits = cipherMaxContentLengthBits;
4040
}
4141

42+
public String dataKeyAlgorithm() {
43+
return _dataKeyAlgorithm;
44+
}
45+
46+
public int dataKeyLengthBits() {
47+
return _dataKeyLengthBits;
48+
}
49+
4250
public String cipherName() {
4351
return _cipherName;
4452
}

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

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,26 @@ public class AESKeyring implements Keyring {
2020
private static final int NONCE_LENGTH_BYTES = 12;
2121
private static final int TAG_LENGTH_BYTES = 16;
2222
private static final int TAG_LENGTH_BITS = TAG_LENGTH_BYTES * 8;
23+
24+
private final DataKeyGenerator _dataKeyGenerator;
2325
private final SecretKey _wrappingKey;
2426

25-
public AESKeyring(SecretKey wrappingKey) {
26-
if (!wrappingKey.getAlgorithm().equals(KEY_ALGORITHM)) {
27-
throw new IllegalArgumentException("Invalid algorithm '" + wrappingKey.getAlgorithm() + "', expecting " + KEY_ALGORITHM);
28-
}
27+
private AESKeyring(Builder builder) {
28+
_dataKeyGenerator = builder._dataKeyGenerator;
29+
_wrappingKey = builder._wrappingKey;
30+
}
2931

30-
_wrappingKey = wrappingKey;
32+
public static Builder builder() {
33+
return new Builder();
3134
}
3235

3336
@Override
3437
public EncryptionMaterials onEncrypt(EncryptionMaterials materials) {
3538
if (materials.plaintextDataKey() == null) {
36-
throw new IllegalStateException("Missing data key to wrap");
39+
SecretKey dataKey = _dataKeyGenerator.generateDataKey(materials.algorithmSuite());
40+
materials = materials.toBuilder()
41+
.plaintextDataKey(dataKey.getEncoded())
42+
.build();
3743
}
3844

3945
try {
@@ -108,4 +114,28 @@ public DecryptionMaterials onDecrypt(final DecryptionMaterials materials, List<E
108114

109115
return materials;
110116
}
117+
118+
public static class Builder {
119+
private DataKeyGenerator _dataKeyGenerator = new DefaultDataKeyGenerator();
120+
private SecretKey _wrappingKey;
121+
122+
private Builder() {}
123+
124+
public Builder wrappingKey(SecretKey wrappingKey) {
125+
if (!wrappingKey.getAlgorithm().equals(KEY_ALGORITHM)) {
126+
throw new IllegalArgumentException("Invalid algorithm '" + wrappingKey.getAlgorithm() + "', expecting " + KEY_ALGORITHM);
127+
}
128+
_wrappingKey = wrappingKey;
129+
return this;
130+
}
131+
132+
public Builder dataKeyGenerator(DataKeyGenerator dataKeyGenerator) {
133+
_dataKeyGenerator = dataKeyGenerator;
134+
return this;
135+
}
136+
137+
public AESKeyring build() {
138+
return new AESKeyring(this);
139+
}
140+
}
111141
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package software.amazon.encryption.s3.materials;
2+
3+
import javax.crypto.SecretKey;
4+
import software.amazon.encryption.s3.algorithms.AlgorithmSuite;
5+
6+
public interface DataKeyGenerator {
7+
SecretKey generateDataKey(AlgorithmSuite algorithmSuite);
8+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package software.amazon.encryption.s3.materials;
2+
3+
import java.security.NoSuchAlgorithmException;
4+
import javax.crypto.KeyGenerator;
5+
import javax.crypto.SecretKey;
6+
import software.amazon.encryption.s3.algorithms.AlgorithmSuite;
7+
8+
public class DefaultDataKeyGenerator implements DataKeyGenerator {
9+
10+
public SecretKey generateDataKey(AlgorithmSuite algorithmSuite) {
11+
KeyGenerator generator;
12+
try {
13+
generator = KeyGenerator.getInstance(algorithmSuite.dataKeyAlgorithm());
14+
} catch (NoSuchAlgorithmException e) {
15+
throw new UnsupportedOperationException("Unable to generate a(n) " + algorithmSuite.dataKeyAlgorithm() + " data key", e);
16+
}
17+
18+
generator.init(algorithmSuite.dataKeyLengthBits());
19+
return generator.generateKey();
20+
}
21+
}

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

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
import software.amazon.encryption.s3.algorithms.AlgorithmSuite;
88

99
public class DefaultMaterialsManager implements MaterialsManager {
10-
// TODO: allow this to be configurable?
11-
private final SecureRandom _secureRandom = new SecureRandom();
1210
private final Keyring _keyring;
1311

1412

@@ -17,29 +15,14 @@ public DefaultMaterialsManager(Keyring keyring) {
1715
}
1816

1917
public EncryptionMaterials getEncryptionMaterials(EncryptionMaterialsRequest request) {
20-
SecretKey key = generateDataKey();
21-
2218
EncryptionMaterials materials = EncryptionMaterials.builder()
2319
.algorithmSuite(AlgorithmSuite.ALG_AES_256_GCM_NO_KDF)
2420
.encryptionContext(request.encryptionContext())
25-
.plaintextDataKey(key.getEncoded())
2621
.build();
2722

2823
return _keyring.onEncrypt(materials);
2924
}
3025

31-
private SecretKey generateDataKey() {
32-
KeyGenerator generator;
33-
try {
34-
generator = KeyGenerator.getInstance("AES");
35-
} catch (NoSuchAlgorithmException e) {
36-
throw new UnsupportedOperationException("Unable to generate an AES key", e);
37-
}
38-
39-
generator.init(256 , _secureRandom);
40-
return generator.generateKey();
41-
}
42-
4326
public DecryptionMaterials getDecryptionMaterials(DecryptionMaterialsRequest request) {
4427
DecryptionMaterials materials = DecryptionMaterials.builder()
4528
.algorithmSuite(request.algorithmSuite())

0 commit comments

Comments
 (0)