Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/com/uid2/admin/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public void run() {
WriteLock writeLock = new WriteLock();
KeyHasher keyHasher = new KeyHasher();
IKeypairGenerator keypairGenerator = new SecureKeypairGenerator();
ISaltRotation saltRotation = new SaltRotation(keyGenerator);
SaltRotation saltRotation = new SaltRotation(keyGenerator);
EncryptionKeyService encryptionKeyService = new EncryptionKeyService(
config, auth, writeLock, encryptionKeyStoreWriter, keysetKeyStoreWriter, keyProvider, keysetKeysProvider, adminKeysetProvider, adminKeysetStoreWriter, keyGenerator, clock);
KeysetManager keysetManager = new KeysetManager(
Expand Down
34 changes: 0 additions & 34 deletions src/main/java/com/uid2/admin/secret/ISaltRotation.java

This file was deleted.

34 changes: 30 additions & 4 deletions src/main/java/com/uid2/admin/secret/SaltRotation.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,18 @@

import static java.util.stream.Collectors.toList;

public class SaltRotation implements ISaltRotation {
public class SaltRotation {
private final IKeyGenerator keyGenerator;
private final long THIRTY_DAYS_IN_MS = Duration.ofDays(30).toMillis();

public SaltRotation(IKeyGenerator keyGenerator) {
this.keyGenerator = keyGenerator;
}

@Override
public Result rotateSalts(RotatingSaltProvider.SaltSnapshot lastSnapshot,
Duration[] minAges,
double fraction,
LocalDate targetDate) throws Exception {

final Instant nextEffective = targetDate.atStartOfDay().toInstant(ZoneOffset.UTC);
final Instant nextExpires = nextEffective.plus(7, ChronoUnit.DAYS);
if (nextEffective.equals(lastSnapshot.getEffective()) || nextEffective.isBefore(lastSnapshot.getEffective())) {
Expand Down Expand Up @@ -63,19 +62,26 @@ private SaltEntry[] updateSalts(SaltEntry[] oldSalts, List<Integer> saltIndexesT
private SaltEntry updateSalt(SaltEntry oldSalt, boolean shouldRotate, long nextEffective) throws Exception {
var currentSalt = shouldRotate ? this.keyGenerator.generateRandomKeyString(32) : oldSalt.currentSalt();
var lastUpdated = shouldRotate ? nextEffective : oldSalt.lastUpdated();
var refreshFrom = calculateRefreshFrom(oldSalt.lastUpdated(), nextEffective);

return new SaltEntry(
oldSalt.id(),
oldSalt.hashedId(),
lastUpdated,
currentSalt,
null,
refreshFrom,
null,
null,
null
);
}

private long calculateRefreshFrom(long lastUpdated, long nextEffective) {
long age = nextEffective - lastUpdated;
long multiplier = age / THIRTY_DAYS_IN_MS + 1;
return lastUpdated + (multiplier * THIRTY_DAYS_IN_MS);
}

private List<Integer> pickSaltIndexesToRotate(
SaltSnapshot lastSnapshot,
Instant nextEffective,
Expand Down Expand Up @@ -125,4 +131,24 @@ private static boolean isBetween(long t, long minInclusive, long maxExclusive) {
return minInclusive <= t && t < maxExclusive;
}

public static class Result {
private final RotatingSaltProvider.SaltSnapshot snapshot; // can be null if new snapshot is not needed
private final String reason; // why you are not getting a new snapshot

private Result(RotatingSaltProvider.SaltSnapshot snapshot, String reason) {
this.snapshot = snapshot;
this.reason = reason;
}

public boolean hasSnapshot() { return snapshot != null; }
public RotatingSaltProvider.SaltSnapshot getSnapshot() { return snapshot; }
public String getReason() { return reason; }

public static Result fromSnapshot(RotatingSaltProvider.SaltSnapshot snapshot) {
return new Result(snapshot, null);
}
public static Result noSnapshot(String reason) {
return new Result(null, reason);
}
}
}
8 changes: 4 additions & 4 deletions src/main/java/com/uid2/admin/vertx/service/SaltService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.uid2.admin.vertx.service;

import com.uid2.admin.auth.AdminAuthMiddleware;
import com.uid2.admin.secret.ISaltRotation;
import com.uid2.admin.secret.SaltRotation;
import com.uid2.admin.store.writer.SaltStoreWriter;
import com.uid2.admin.vertx.RequestUtil;
import com.uid2.admin.vertx.ResponseUtil;
Expand Down Expand Up @@ -30,13 +30,13 @@ public class SaltService implements IService {
private final WriteLock writeLock;
private final SaltStoreWriter storageManager;
private final RotatingSaltProvider saltProvider;
private final ISaltRotation saltRotation;
private final SaltRotation saltRotation;

public SaltService(AdminAuthMiddleware auth,
WriteLock writeLock,
SaltStoreWriter storageManager,
RotatingSaltProvider saltProvider,
ISaltRotation saltRotation) {
SaltRotation saltRotation) {
this.auth = auth;
this.writeLock = writeLock;
this.storageManager = storageManager;
Expand Down Expand Up @@ -89,7 +89,7 @@ private void handleSaltRotate(RoutingContext rc) {
final List<RotatingSaltProvider.SaltSnapshot> snapshots = this.saltProvider.getSnapshots();
final RotatingSaltProvider.SaltSnapshot lastSnapshot = snapshots.get(snapshots.size() - 1);

final ISaltRotation.Result result = saltRotation.rotateSalts(
final SaltRotation.Result result = saltRotation.rotateSalts(
lastSnapshot, minAges, fraction.get(), targetDate);
if (!result.hasSnapshot()) {
ResponseUtil.error(rc, 200, result.getReason());
Expand Down
Loading