mirror of
https://github.com/google/nomulus
synced 2026-06-09 16:33:02 +00:00
Use time-constant comparison in password testing (#3090)
Normal comparison exits out once a difference is found so theoretically a time variance can leak information. This isn't really a huge deal but is probably still worth doing.
This commit is contained in:
@@ -44,6 +44,8 @@ import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@@ -134,7 +136,9 @@ public final class ResourceFlowUtils {
|
||||
}
|
||||
String authPassword = authInfo.getPw().getValue();
|
||||
String domainPassword = domain.getAuthInfo().getPw().getValue();
|
||||
if (!domainPassword.equals(authPassword)) {
|
||||
if (!MessageDigest.isEqual(
|
||||
authPassword.getBytes(StandardCharsets.UTF_8),
|
||||
domainPassword.getBytes(StandardCharsets.UTF_8))) {
|
||||
throw new BadAuthInfoForResourceException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.google.common.hash.Hashing;
|
||||
import google.registry.model.server.ServerSecret;
|
||||
import google.registry.util.Clock;
|
||||
import jakarta.inject.Inject;
|
||||
import java.security.MessageDigest;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
@@ -102,7 +103,7 @@ public final class XsrfTokenManager {
|
||||
}
|
||||
// Reconstruct the token to verify validity.
|
||||
String reconstructedToken = encodeToken(ServerSecret.get().asBytes(), email, timestampMillis);
|
||||
if (!token.equals(reconstructedToken)) {
|
||||
if (!MessageDigest.isEqual(token.getBytes(UTF_8), reconstructedToken.getBytes(UTF_8))) {
|
||||
logger.atWarning().log(
|
||||
"Reconstructed XSRF mismatch (got != expected): %s != %s", token, reconstructedToken);
|
||||
return false;
|
||||
|
||||
@@ -22,8 +22,8 @@ import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import org.bouncycastle.crypto.generators.Argon2BytesGenerator;
|
||||
import org.bouncycastle.crypto.generators.SCrypt;
|
||||
@@ -143,11 +143,11 @@ public final class PasswordUtils {
|
||||
byte[] decodedSalt = base64().decode(salt);
|
||||
byte[] decodedPassword = password.getBytes(US_ASCII);
|
||||
|
||||
if (Arrays.equals(decodedHash, ARGON_2_ID.hash(decodedPassword, decodedSalt))) {
|
||||
if (MessageDigest.isEqual(decodedHash, ARGON_2_ID.hash(decodedPassword, decodedSalt))) {
|
||||
logger.atInfo().log("ARGON_2_ID hash verified.");
|
||||
return Optional.of(ARGON_2_ID);
|
||||
}
|
||||
if (Arrays.equals(decodedHash, SCRYPT_P_1.hash(decodedPassword, decodedSalt))) {
|
||||
if (MessageDigest.isEqual(decodedHash, SCRYPT_P_1.hash(decodedPassword, decodedSalt))) {
|
||||
logger.atInfo().log("SCRYPT_P_1 hash verified.");
|
||||
return Optional.of(SCRYPT_P_1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user