diff --git a/src/main/java/com/uid2/shared/model/SaltEntry.java b/src/main/java/com/uid2/shared/model/SaltEntry.java index 9405e8fb..6505415a 100644 --- a/src/main/java/com/uid2/shared/model/SaltEntry.java +++ b/src/main/java/com/uid2/shared/model/SaltEntry.java @@ -9,8 +9,8 @@ public record SaltEntry( Long refreshFrom, // needs to be nullable until V3 Identity Map is fully rolled out String previousSalt, - KeyMaterial currentKey, - KeyMaterial previousKey + KeyMaterial currentKeySalt, + KeyMaterial previousKeySalt ) { @Override public String toString() { @@ -18,11 +18,11 @@ public String toString() { "id=" + id + ", hashedId='" + hashedId + '\'' + ", lastUpdated=" + lastUpdated + - ", currentSalt=" + + ", currentSalt=" + (currentSalt == null ? "null" : "") + ", refreshFrom=" + refreshFrom + - ", previousSalt=" + - ", currentKey=" + currentKey + - ", previousKey=" + previousKey + + ", previousSalt=" + (previousSalt == null ? "null" : "") + + ", currentKeySalt=" + currentKeySalt + + ", previousKeySalt=" + previousKeySalt + '}'; } @@ -36,7 +36,7 @@ public String toString() { return "KeyMaterial{" + "id=" + id + ", key=" + - ", currentSalt=" + + ", salt=" + '}'; } } diff --git a/src/main/java/com/uid2/shared/store/salt/RotatingSaltProvider.java b/src/main/java/com/uid2/shared/store/salt/RotatingSaltProvider.java index 84f90f8e..79ed3815 100644 --- a/src/main/java/com/uid2/shared/store/salt/RotatingSaltProvider.java +++ b/src/main/java/com/uid2/shared/store/salt/RotatingSaltProvider.java @@ -41,8 +41,8 @@ } 2. currentSalt file format - , , - 9000099,1614556800000,currentSalt + ,,,,,,,,,, + 9000099,1614556800000,currentSalt,1756252800000,previousSalt,100,currentKeyKey,currentKeySalt,1,previousKeyKey,previousKeySalt */ public class RotatingSaltProvider implements ISaltProvider, IMetadataVersionedStore { private static final Logger LOGGER = LoggerFactory.getLogger(RotatingSaltProvider.class); @@ -159,10 +159,10 @@ public SaltSnapshot(Instant effective, Instant expires, SaltEntry[] entries, Str this.entries = entries; this.firstLevelSalt = firstLevelSalt; if (entries.length == 1_048_576) { - LOGGER.info("Total currentSalt entries 1 million, {}, special production currentSalt entry indexer", entries.length); + LOGGER.info("Total salt bucket entries 1 million, {}, special production currentSalt entry indexer", entries.length); this.saltEntryIndexer = MILLION_ENTRY_INDEXER; } else { - LOGGER.warn("Total currentSalt entries {}, using slower mod-based indexer", entries.length); + LOGGER.warn("Total salt bucket entries {}, using slower mod-based indexer", entries.length); this.saltEntryIndexer = MOD_BASED_INDEXER; } } diff --git a/src/main/java/com/uid2/shared/store/salt/SaltFileParser.java b/src/main/java/com/uid2/shared/store/salt/SaltFileParser.java index 067b65df..4acb3d1c 100644 --- a/src/main/java/com/uid2/shared/store/salt/SaltFileParser.java +++ b/src/main/java/com/uid2/shared/store/salt/SaltFileParser.java @@ -31,23 +31,23 @@ private SaltEntry parseLine(String line, int lineNumber) { final long id = Integer.parseInt(fields[0]); final String hashedId = this.idHashingScheme.encode(id); final long lastUpdated = Long.parseLong(fields[1]); - final String salt = fields[2]; + final String salt = trimToNull(fields[2]); final long refreshFrom = Long.parseLong(fields[3]); final String previousSalt = trimToNull(fields[4]); // TODO: The fields below should stop being optional once refreshable UIDs features get rolled out in production. We can remove them one by one as necessary. // AU, 2025/07/28 - SaltEntry.KeyMaterial currentKey = null; - SaltEntry.KeyMaterial previousKey = null; + SaltEntry.KeyMaterial currentKeySalt = null; + SaltEntry.KeyMaterial previousKeySalt = null; if (trimToNull(fields[5]) != null && trimToNull(fields[6]) != null) { - currentKey = new SaltEntry.KeyMaterial(Integer.parseInt(fields[5]), fields[6], fields[7]); + currentKeySalt = new SaltEntry.KeyMaterial(Integer.parseInt(fields[5]), fields[6], fields[7]); } if (trimToNull(fields[8]) != null && trimToNull(fields[9]) != null) { - previousKey = new SaltEntry.KeyMaterial(Integer.parseInt(fields[8]), fields[9], fields[10]); + previousKeySalt = new SaltEntry.KeyMaterial(Integer.parseInt(fields[8]), fields[9], fields[10]); } - return new SaltEntry(id, hashedId, lastUpdated, salt, refreshFrom, previousSalt, currentKey, previousKey); + return new SaltEntry(id, hashedId, lastUpdated, salt, refreshFrom, previousSalt, currentKeySalt, previousKeySalt); } catch (Exception e) { throw new RuntimeException("Trouble parsing Salt Entry, line number: " + lineNumber, e); } diff --git a/src/test/java/com/uid2/shared/store/salt/SaltFileParserTest.java b/src/test/java/com/uid2/shared/store/salt/SaltFileParserTest.java index 8461243d..b4dfbecd 100644 --- a/src/test/java/com/uid2/shared/store/salt/SaltFileParserTest.java +++ b/src/test/java/com/uid2/shared/store/salt/SaltFileParserTest.java @@ -14,6 +14,8 @@ class SaltFileParserTest { private final String hashed1 = hashingScheme.encode(1); private final String hashed2 = hashingScheme.encode(2); private final String hashed3 = hashingScheme.encode(3); + private final String hashed4 = hashingScheme.encode(4); + private final String hashed5 = hashingScheme.encode(5); @Test void parsesSaltFileWithAllFields() { @@ -71,4 +73,28 @@ void parsesSaltFileWithNullValuesForKeyFields() { }; assertThat(actual).isEqualTo(expected); } + + @Test + void parseSaltFileWithEmptyValuesMixedSaltKeyFields() { + var file = """ +1,100,,1000,old_salt,,,,,, +2,200,,2000,old_salt,0,current_key_key,current_key_salt,,, +3,300,,3000,,0,current_key_key,current_key_salt,,, +4,400,,4000,,0,current_key_key,current_key_salt,1,previous_key_key,previous_key_salt +5,500,salt,5000,,,,,1,previous_key_key,previous_key_salt +"""; + SaltEntry[] actual = parser.parseFile(file, 5); + + var expectedCurrentKey = new KeyMaterial(0, "current_key_key", "current_key_salt"); + var expectedPreviousKey = new KeyMaterial(1, "previous_key_key", "previous_key_salt"); + + SaltEntry[] expected = new SaltEntry[]{ + new SaltEntry(1, hashed1, 100, null, 1000L, "old_salt",null, null), + new SaltEntry(2, hashed2, 200, null, 2000L, "old_salt", expectedCurrentKey,null), + new SaltEntry(3, hashed3, 300, null, 3000L, null, expectedCurrentKey, null), + new SaltEntry(4, hashed4, 400, null, 4000L, null, expectedCurrentKey, expectedPreviousKey), + new SaltEntry(5, hashed5, 500, "salt", 5000L, null,null, expectedPreviousKey) + }; + assertThat(actual).isEqualTo(expected); + } }