Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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,17 @@

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

public class SaltRotation implements ISaltRotation {
public class SaltRotation {
private final IKeyGenerator keyGenerator;

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 +61,27 @@ 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 thirtyDaysMillis = 2592000000L;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also use Duration.ofDays(30).toMillis();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done 1 million times in a loop so I wanted to reduce logic to minimum. Perhaps could move it to class level so it doesn't get recomputed every time.

long age = nextEffective - lastUpdated;
long multiplier = age / thirtyDaysMillis + 1;
return lastUpdated + (multiplier * thirtyDaysMillis);
}

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