// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.core.auth;

import java.util.Base64;
import java.nio.charset.StandardCharsets;
import javax.annotation.Nullable;
import java.security.cert.CertificateEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.security.MessageDigest;
import javax.annotation.Nonnull;
import java.security.cert.X509Certificate;
import com.hypixel.hytale.logger.HytaleLogger;

public class CertificateUtil
{
    private static final HytaleLogger LOGGER;
    
    @Nullable
    public static String computeCertificateFingerprint(@Nonnull final X509Certificate certificate) {
        try {
            final MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
            final byte[] certBytes = certificate.getEncoded();
            final byte[] hash = sha256.digest(certBytes);
            return base64UrlEncode(hash);
        }
        catch (final NoSuchAlgorithmException e) {
            CertificateUtil.LOGGER.at(Level.SEVERE).withCause(e).log("SHA-256 algorithm not available");
            return null;
        }
        catch (final CertificateEncodingException e2) {
            CertificateUtil.LOGGER.at(Level.WARNING).withCause(e2).log("Failed to encode certificate");
            return null;
        }
    }
    
    public static boolean validateCertificateBinding(@Nullable final String jwtFingerprint, @Nullable final X509Certificate clientCert) {
        if (jwtFingerprint == null || jwtFingerprint.isEmpty()) {
            CertificateUtil.LOGGER.at(Level.WARNING).log("JWT missing certificate fingerprint (cnf.x5t#S256) - rejecting token");
            return false;
        }
        if (clientCert == null) {
            CertificateUtil.LOGGER.at(Level.WARNING).log("No client certificate present in mTLS connection - rejecting token");
            return false;
        }
        final String actualFingerprint = computeCertificateFingerprint(clientCert);
        if (actualFingerprint == null) {
            CertificateUtil.LOGGER.at(Level.WARNING).log("Failed to compute client certificate fingerprint");
            return false;
        }
        final boolean matches = timingSafeEquals(jwtFingerprint, actualFingerprint);
        if (!matches) {
            CertificateUtil.LOGGER.at(Level.WARNING).log("Certificate fingerprint mismatch! JWT: %s, Actual: %s", jwtFingerprint, actualFingerprint);
        }
        else {
            CertificateUtil.LOGGER.at(Level.INFO).log("Certificate binding validated successfully");
        }
        return matches;
    }
    
    public static boolean timingSafeEquals(final String a, final String b) {
        if (a == null || b == null) {
            return a == b;
        }
        final byte[] aBytes = a.getBytes(StandardCharsets.UTF_8);
        final byte[] bBytes = b.getBytes(StandardCharsets.UTF_8);
        return MessageDigest.isEqual(aBytes, bBytes);
    }
    
    private static String base64UrlEncode(final byte[] input) {
        final String base64 = Base64.getEncoder().encodeToString(input);
        return base64.replace('+', '-').replace('/', '_').replace("=", "");
    }
    
    static {
        LOGGER = HytaleLogger.forEnclosingClass();
    }
}
