Skip to content

Commit 1a23d0d

Browse files
Had to adjust to work with 1mil salts
1 parent b2e9b68 commit 1a23d0d

File tree

2 files changed

+77
-16
lines changed

2 files changed

+77
-16
lines changed
Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package com.uid2.shared.util;
22

33
import java.io.InputStream;
4+
5+
import com.fasterxml.jackson.core.JsonFactory;
6+
import com.fasterxml.jackson.core.JsonParser;
7+
import com.fasterxml.jackson.core.JsonToken;
48
import com.uid2.shared.encryption.AesGcm;
59
import com.uid2.shared.model.CloudEncryptionKey;
610

@@ -13,31 +17,37 @@
1317

1418
public class CloudEncryptionHelpers {
1519
public static String decryptInputStream(InputStream inputStream, RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider) throws IOException {
16-
String encryptedContent = inputStreamToString(inputStream);
17-
JsonObject json = new JsonObject(encryptedContent);
18-
int keyId = json.getInteger("key_id");
19-
String encryptedPayload = json.getString("encrypted_payload");
20+
JsonFactory factory = new JsonFactory();
21+
JsonParser parser = factory.createParser(inputStream);
22+
int keyId = -1;
23+
byte[] encryptedPayload = null;
24+
parser.nextToken();
25+
while (parser.nextToken() != JsonToken.END_OBJECT) {
26+
String fieldName = parser.getCurrentName();
27+
if(fieldName.equals("key_id")) {
28+
parser.nextToken();
29+
keyId = parser.getIntValue();
30+
}
31+
if(fieldName.equals("encrypted_payload")) {
32+
parser.nextToken();
33+
encryptedPayload = parser.getBinaryValue();
34+
}
35+
}
36+
37+
if(keyId == -1 || encryptedPayload == null) {
38+
throw new IllegalStateException("failed to parse json");
39+
}
40+
2041
CloudEncryptionKey decryptionKey = cloudEncryptionKeyProvider.getKey(keyId);
2142

2243
if (decryptionKey == null) {
2344
throw new IllegalStateException("No matching S3 key found for decryption for key ID: " + keyId);
2445
}
2546

2647
byte[] secret = Base64.getDecoder().decode(decryptionKey.getSecret());
27-
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedPayload);
48+
byte[] encryptedBytes = encryptedPayload;
2849
byte[] decryptedBytes = AesGcm.decrypt(encryptedBytes, 0, secret);
2950

3051
return new String(decryptedBytes, StandardCharsets.UTF_8);
3152
}
32-
33-
public static String inputStreamToString(InputStream inputStream) throws IOException {
34-
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
35-
StringBuilder stringBuilder = new StringBuilder();
36-
String line;
37-
while ((line = reader.readLine()) != null) {
38-
stringBuilder.append(line);
39-
}
40-
return stringBuilder.toString();
41-
}
42-
}
4353
}

src/test/java/com/uid2/shared/store/EncryptedRotatingSaltProviderTest.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,57 @@ public void loadSaltSingleVersion() throws Exception {
123123
assertTrue(snapshot.getModifiedSince(Instant.now().minus(1, ChronoUnit.HOURS)).isEmpty());
124124
}
125125

126+
@Test
127+
public void loadSaltSingleVersion1mil() throws Exception {
128+
final String FIRST_LEVEL_SALT = "first_level_salt_value";
129+
final String ID_PREFIX = "a";
130+
final String ID_SECRET = "m3yMIcbg9vCaFLJsn4m4PfruZnvAZ72OxmFG5QsGMOw=";
131+
132+
final Instant generatedTime = Instant.now().minus(1, ChronoUnit.DAYS);
133+
final Instant expireTime = Instant.now().plus(365, ChronoUnit.DAYS);
134+
135+
final JsonObject metadataJson = new JsonObject();
136+
{
137+
metadataJson.put("version", 2);
138+
metadataJson.put("generated", generatedTime.getEpochSecond() * 1000L);
139+
metadataJson.put("first_level", FIRST_LEVEL_SALT);
140+
metadataJson.put("id_prefix", ID_PREFIX);
141+
metadataJson.put("id_secret", ID_SECRET);
142+
final JsonArray saltsRefList = new JsonArray();
143+
{
144+
final JsonObject saltsRef = new JsonObject();
145+
saltsRef.put("effective", generatedTime.getEpochSecond() * 1000L);
146+
saltsRef.put("expires", expireTime.getEpochSecond() * 1000L);
147+
saltsRef.put("location", "salts.txt");
148+
saltsRef.put("size", 1000000);
149+
saltsRefList.add(saltsRef);
150+
}
151+
metadataJson.put("salts", saltsRefList);
152+
}
153+
154+
final String effectiveTimeString = String.valueOf(generatedTime.getEpochSecond() * 1000L);
155+
StringBuilder salts = new StringBuilder();
156+
for (int i = 0; i < 1000000; i++) {
157+
salts.append(i).append(",").append(effectiveTimeString).append(",").append("salt-string").append("\n");
158+
}
159+
160+
when(cloudStorage.download("metadata"))
161+
.thenReturn(new ByteArrayInputStream(metadataJson.toString().getBytes(StandardCharsets.US_ASCII)));
162+
when(cloudStorage.download("salts.txt"))
163+
.thenReturn(getEncryptedStream(salts.toString()));
164+
165+
EncryptedRotatingSaltProvider saltsProvider = new EncryptedRotatingSaltProvider(
166+
cloudStorage, "metadata", keyProvider);
167+
168+
final JsonObject loadedMetadata = saltsProvider.getMetadata();
169+
saltsProvider.loadContent(loadedMetadata);
170+
assertEquals(2, saltsProvider.getVersion(loadedMetadata));
171+
172+
final ISaltProvider.ISaltSnapshot snapshot = saltsProvider.getSnapshot(Instant.now());
173+
assertEquals(FIRST_LEVEL_SALT, snapshot.getFirstLevelSalt());
174+
assertTrue(snapshot.getModifiedSince(Instant.now().minus(1, ChronoUnit.HOURS)).isEmpty());
175+
}
176+
126177
@Test
127178
public void loadSaltMultipleVersions() throws Exception {
128179
final String FIRST_LEVEL_SALT = "first_level_salt_value";

0 commit comments

Comments
 (0)