11package com .uid2 .admin .salt ;
22
3+ import com .uid2 .admin .AdminConst ;
34import com .uid2 .shared .model .SaltEntry ;
45import com .uid2 .shared .secret .IKeyGenerator ;
56
67import com .uid2 .shared .store .salt .ISaltProvider .ISaltSnapshot ;
78import com .uid2 .shared .store .salt .RotatingSaltProvider .SaltSnapshot ;
9+ import io .vertx .core .json .JsonObject ;
810import lombok .Getter ;
911import org .slf4j .Logger ;
1012import org .slf4j .LoggerFactory ;
1719public class SaltRotation {
1820 private static final long THIRTY_DAYS_IN_MS = Duration .ofDays (30 ).toMillis ();
1921 private static final double MAX_SALT_PERCENTAGE = 0.8 ;
22+ private final boolean ENABLE_V4_RAW_UID ;
2023
2124 private final IKeyGenerator keyGenerator ;
25+
2226 private static final Logger LOGGER = LoggerFactory .getLogger (SaltRotation .class );
2327
24- public SaltRotation (IKeyGenerator keyGenerator ) {
28+ public SaltRotation (IKeyGenerator keyGenerator , JsonObject config ) {
2529 this .keyGenerator = keyGenerator ;
30+ this .ENABLE_V4_RAW_UID = config .getBoolean (AdminConst .ENABLE_V4_RAW_UID , false );
2631 }
2732
2833 public Result rotateSalts (
@@ -99,21 +104,24 @@ private boolean isRefreshable(TargetDate targetDate, SaltEntry salt) {
99104 }
100105
101106 private SaltEntry [] rotateSalts (SaltEntry [] oldSalts , List <SaltEntry > saltsToRotate , TargetDate targetDate ) throws Exception {
107+ var keyIdGenerator = new KeyIdGenerator (oldSalts );
102108 var saltIdsToRotate = saltsToRotate .stream ().map (SaltEntry ::id ).collect (Collectors .toSet ());
103109
104110 var updatedSalts = new SaltEntry [oldSalts .length ];
105111 for (int i = 0 ; i < oldSalts .length ; i ++) {
106112 var shouldRotate = saltIdsToRotate .contains (oldSalts [i ].id ());
107- updatedSalts [i ] = updateSalt (oldSalts [i ], targetDate , shouldRotate );
113+ updatedSalts [i ] = updateSalt (oldSalts [i ], targetDate , shouldRotate , keyIdGenerator );
108114 }
109115 return updatedSalts ;
110116 }
111117
112- private SaltEntry updateSalt (SaltEntry oldSalt , TargetDate targetDate , boolean shouldRotate ) throws Exception {
113- var currentSalt = shouldRotate ? this .keyGenerator .generateRandomKeyString (32 ) : oldSalt .currentSalt ();
118+ private SaltEntry updateSalt (SaltEntry oldSalt , TargetDate targetDate , boolean shouldRotate , KeyIdGenerator keyIdGenerator ) throws Exception {
114119 var lastUpdated = shouldRotate ? targetDate .asEpochMs () : oldSalt .lastUpdated ();
115120 var refreshFrom = calculateRefreshFrom (oldSalt , targetDate );
121+ var currentSalt = calculateCurrentSalt (oldSalt , shouldRotate );
116122 var previousSalt = calculatePreviousSalt (oldSalt , shouldRotate , targetDate );
123+ var currentKey = calculateCurrentKey (oldSalt , shouldRotate , keyIdGenerator );
124+ var previousKey = calculatePreviousKey (oldSalt ,shouldRotate , targetDate );
117125
118126 return new SaltEntry (
119127 oldSalt .id (),
@@ -122,8 +130,8 @@ private SaltEntry updateSalt(SaltEntry oldSalt, TargetDate targetDate, boolean s
122130 currentSalt ,
123131 refreshFrom ,
124132 previousSalt ,
125- null ,
126- null
133+ currentKey ,
134+ previousKey
127135 );
128136 }
129137
@@ -132,6 +140,12 @@ private long calculateRefreshFrom(SaltEntry salt, TargetDate targetDate) {
132140 return Instant .ofEpochMilli (salt .lastUpdated ()).truncatedTo (ChronoUnit .DAYS ).toEpochMilli () + (multiplier * THIRTY_DAYS_IN_MS );
133141 }
134142
143+ private String calculateCurrentSalt (SaltEntry salt , boolean shouldRotate ) throws Exception {
144+ return shouldRotate ?
145+ ENABLE_V4_RAW_UID ? null : this .keyGenerator .generateRandomKeyString (32 )
146+ : salt .currentSalt ();
147+ }
148+
135149 private String calculatePreviousSalt (SaltEntry salt , boolean shouldRotate , TargetDate targetDate ) {
136150 if (shouldRotate ) {
137151 return salt .currentSalt ();
@@ -142,6 +156,31 @@ private String calculatePreviousSalt(SaltEntry salt, boolean shouldRotate, Targe
142156 return null ;
143157 }
144158
159+ private SaltEntry .KeyMaterial calculateCurrentKey (SaltEntry salt , boolean shouldRotate , KeyIdGenerator keyIdGenerator ) throws Exception {
160+ if (shouldRotate ) {
161+ if (ENABLE_V4_RAW_UID ) {
162+ return new SaltEntry .KeyMaterial (
163+ keyIdGenerator .getNextKeyId (),
164+ this .keyGenerator .generateRandomKeyString (32 ),
165+ this .keyGenerator .generateRandomKeyString (32 )
166+ );
167+ } else {
168+ return null ;
169+ }
170+ }
171+ return salt .currentKey ();
172+ }
173+
174+ private SaltEntry .KeyMaterial calculatePreviousKey (SaltEntry salt , boolean shouldRotate , TargetDate targetDate ) {
175+ if (shouldRotate ) {
176+ return salt .currentKey ();
177+ }
178+ if (targetDate .saltAgeInDays (salt ) < 90 ) {
179+ return salt .previousKey ();
180+ }
181+ return null ;
182+ }
183+
145184 private List <SaltEntry > pickSaltsToRotate (
146185 Set <SaltEntry > refreshableSalts ,
147186 TargetDate targetDate ,
0 commit comments