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

package com.google.crypto.tink.jwt.internal;

import com.google.crypto.tink.internal.Util;
import com.google.crypto.tink.internal.MutableSerializationRegistry;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.ExtensionRegistryLite;
import com.google.crypto.tink.util.SecretBigInteger;
import com.google.crypto.tink.proto.KeyData;
import javax.annotation.Nullable;
import com.google.crypto.tink.SecretKeyAccess;
import com.google.crypto.tink.proto.KeyTemplate;
import java.security.GeneralSecurityException;
import com.google.crypto.tink.proto.JwtRsaSsaPssKeyFormat;
import com.google.crypto.tink.internal.BigIntegerEncoding;
import com.google.protobuf.ByteString;
import java.math.BigInteger;
import com.google.crypto.tink.proto.OutputPrefixType;
import com.google.crypto.tink.proto.JwtRsaSsaPssAlgorithm;
import com.google.crypto.tink.internal.EnumTypeProtoConverter;
import com.google.crypto.tink.jwt.JwtRsaSsaPssPrivateKey;
import com.google.crypto.tink.internal.KeyParser;
import com.google.crypto.tink.internal.ProtoKeySerialization;
import com.google.crypto.tink.jwt.JwtRsaSsaPssPublicKey;
import com.google.crypto.tink.internal.KeySerializer;
import com.google.crypto.tink.internal.ParametersParser;
import com.google.crypto.tink.internal.ProtoParametersSerialization;
import com.google.crypto.tink.jwt.JwtRsaSsaPssParameters;
import com.google.crypto.tink.internal.ParametersSerializer;
import com.google.crypto.tink.util.Bytes;
import com.google.crypto.tink.AccessesPartialKey;

@AccessesPartialKey
public final class JwtRsaSsaPssProtoSerialization
{
    private static final String PRIVATE_TYPE_URL = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey";
    private static final Bytes PRIVATE_TYPE_URL_BYTES;
    private static final String PUBLIC_TYPE_URL = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey";
    private static final Bytes PUBLIC_TYPE_URL_BYTES;
    private static final ParametersSerializer<JwtRsaSsaPssParameters, ProtoParametersSerialization> PARAMETERS_SERIALIZER;
    private static final ParametersParser<ProtoParametersSerialization> PARAMETERS_PARSER;
    private static final KeySerializer<JwtRsaSsaPssPublicKey, ProtoKeySerialization> PUBLIC_KEY_SERIALIZER;
    private static final KeyParser<ProtoKeySerialization> PUBLIC_KEY_PARSER;
    private static final KeySerializer<JwtRsaSsaPssPrivateKey, ProtoKeySerialization> PRIVATE_KEY_SERIALIZER;
    private static final KeyParser<ProtoKeySerialization> PRIVATE_KEY_PARSER;
    private static final EnumTypeProtoConverter<JwtRsaSsaPssAlgorithm, JwtRsaSsaPssParameters.Algorithm> ALGORITHM_CONVERTER;
    
    private static OutputPrefixType toProtoOutputPrefixType(final JwtRsaSsaPssParameters parameters) {
        if (parameters.getKidStrategy().equals(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID)) {
            return OutputPrefixType.TINK;
        }
        return OutputPrefixType.RAW;
    }
    
    private static ByteString encodeBigInteger(final BigInteger i) {
        final byte[] encoded = BigIntegerEncoding.toBigEndianBytes(i);
        return ByteString.copyFrom(encoded);
    }
    
    private static JwtRsaSsaPssKeyFormat getProtoKeyFormat(final JwtRsaSsaPssParameters parameters) throws GeneralSecurityException {
        if (!parameters.getKidStrategy().equals(JwtRsaSsaPssParameters.KidStrategy.IGNORED) && !parameters.getKidStrategy().equals(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID)) {
            throw new GeneralSecurityException("Unable to serialize Parameters object with KidStrategy " + parameters.getKidStrategy());
        }
        return JwtRsaSsaPssKeyFormat.newBuilder().setVersion(0).setAlgorithm(JwtRsaSsaPssProtoSerialization.ALGORITHM_CONVERTER.toProtoEnum(parameters.getAlgorithm())).setModulusSizeInBits(parameters.getModulusSizeBits()).setPublicExponent(encodeBigInteger(parameters.getPublicExponent())).build();
    }
    
    private static ProtoParametersSerialization serializeParameters(final JwtRsaSsaPssParameters parameters) throws GeneralSecurityException {
        final OutputPrefixType outputPrefixType = toProtoOutputPrefixType(parameters);
        return ProtoParametersSerialization.create(KeyTemplate.newBuilder().setTypeUrl("type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey").setValue(getProtoKeyFormat(parameters).toByteString()).setOutputPrefixType(outputPrefixType).build());
    }
    
    private static com.google.crypto.tink.proto.JwtRsaSsaPssPublicKey getProtoPublicKey(final JwtRsaSsaPssPublicKey key) throws GeneralSecurityException {
        final com.google.crypto.tink.proto.JwtRsaSsaPssPublicKey.Builder builder = com.google.crypto.tink.proto.JwtRsaSsaPssPublicKey.newBuilder().setVersion(0).setAlgorithm(JwtRsaSsaPssProtoSerialization.ALGORITHM_CONVERTER.toProtoEnum(key.getParameters().getAlgorithm())).setN(encodeBigInteger(key.getModulus())).setE(encodeBigInteger(key.getParameters().getPublicExponent()));
        if (key.getParameters().getKidStrategy().equals(JwtRsaSsaPssParameters.KidStrategy.CUSTOM)) {
            builder.setCustomKid(com.google.crypto.tink.proto.JwtRsaSsaPssPublicKey.CustomKid.newBuilder().setValue(key.getKid().get()).build());
        }
        return builder.build();
    }
    
    private static ProtoKeySerialization serializePublicKey(final JwtRsaSsaPssPublicKey key, @Nullable final SecretKeyAccess access) throws GeneralSecurityException {
        return ProtoKeySerialization.create("type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey", getProtoPublicKey(key).toByteString(), KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC, toProtoOutputPrefixType(key.getParameters()), key.getIdRequirementOrNull());
    }
    
    private static ByteString encodeSecretBigInteger(final SecretBigInteger i, final SecretKeyAccess access) {
        return encodeBigInteger(i.getBigInteger(access));
    }
    
    private static ProtoKeySerialization serializePrivateKey(final JwtRsaSsaPssPrivateKey key, @Nullable final SecretKeyAccess access) throws GeneralSecurityException {
        final SecretKeyAccess a = SecretKeyAccess.requireAccess(access);
        final com.google.crypto.tink.proto.JwtRsaSsaPssPrivateKey protoPrivateKey = com.google.crypto.tink.proto.JwtRsaSsaPssPrivateKey.newBuilder().setVersion(0).setPublicKey(getProtoPublicKey(key.getPublicKey())).setD(encodeSecretBigInteger(key.getPrivateExponent(), a)).setP(encodeSecretBigInteger(key.getPrimeP(), a)).setQ(encodeSecretBigInteger(key.getPrimeQ(), a)).setDp(encodeSecretBigInteger(key.getPrimeExponentP(), a)).setDq(encodeSecretBigInteger(key.getPrimeExponentQ(), a)).setCrt(encodeSecretBigInteger(key.getCrtCoefficient(), a)).build();
        return ProtoKeySerialization.create("type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey", protoPrivateKey.toByteString(), KeyData.KeyMaterialType.ASYMMETRIC_PRIVATE, toProtoOutputPrefixType(key.getParameters()), key.getIdRequirementOrNull());
    }
    
    private static BigInteger decodeBigInteger(final ByteString data) {
        return BigIntegerEncoding.fromUnsignedBigEndianBytes(data.toByteArray());
    }
    
    private static void validateVersion(final int version) throws GeneralSecurityException {
        if (version != 0) {
            throw new GeneralSecurityException("Parsing failed: unknown version " + version);
        }
    }
    
    private static JwtRsaSsaPssParameters parseParameters(final ProtoParametersSerialization serialization) throws GeneralSecurityException {
        if (!serialization.getKeyTemplate().getTypeUrl().equals("type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey")) {
            throw new IllegalArgumentException("Wrong type URL in call to JwtRsaSsaPssProtoSerialization.parseParameters: " + serialization.getKeyTemplate().getTypeUrl());
        }
        JwtRsaSsaPssKeyFormat format;
        try {
            format = JwtRsaSsaPssKeyFormat.parseFrom(serialization.getKeyTemplate().getValue(), ExtensionRegistryLite.getEmptyRegistry());
        }
        catch (final InvalidProtocolBufferException e) {
            throw new GeneralSecurityException("Parsing JwtRsaSsaPssParameters failed: ", e);
        }
        validateVersion(format.getVersion());
        JwtRsaSsaPssParameters.KidStrategy kidStrategy = null;
        if (serialization.getKeyTemplate().getOutputPrefixType().equals(OutputPrefixType.TINK)) {
            kidStrategy = JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID;
        }
        if (serialization.getKeyTemplate().getOutputPrefixType().equals(OutputPrefixType.RAW)) {
            kidStrategy = JwtRsaSsaPssParameters.KidStrategy.IGNORED;
        }
        if (kidStrategy == null) {
            throw new GeneralSecurityException("Invalid OutputPrefixType for JwtHmacKeyFormat");
        }
        return JwtRsaSsaPssParameters.builder().setKidStrategy(kidStrategy).setAlgorithm(JwtRsaSsaPssProtoSerialization.ALGORITHM_CONVERTER.fromProtoEnum(format.getAlgorithm())).setPublicExponent(decodeBigInteger(format.getPublicExponent())).setModulusSizeBits(format.getModulusSizeInBits()).build();
    }
    
    private static JwtRsaSsaPssPublicKey getPublicKeyFromProto(final com.google.crypto.tink.proto.JwtRsaSsaPssPublicKey protoKey, final OutputPrefixType outputPrefixType, @Nullable final Integer idRequirement) throws GeneralSecurityException {
        validateVersion(protoKey.getVersion());
        final JwtRsaSsaPssParameters.Builder parametersBuilder = JwtRsaSsaPssParameters.builder();
        final JwtRsaSsaPssPublicKey.Builder keyBuilder = JwtRsaSsaPssPublicKey.builder();
        if (outputPrefixType.equals(OutputPrefixType.TINK)) {
            if (protoKey.hasCustomKid()) {
                throw new GeneralSecurityException("Keys serialized with OutputPrefixType TINK should not have a custom kid");
            }
            if (idRequirement == null) {
                throw new GeneralSecurityException("Keys serialized with OutputPrefixType TINK need an ID Requirement");
            }
            parametersBuilder.setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.BASE64_ENCODED_KEY_ID);
            keyBuilder.setIdRequirement(idRequirement);
        }
        else if (outputPrefixType.equals(OutputPrefixType.RAW)) {
            if (protoKey.hasCustomKid()) {
                parametersBuilder.setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.CUSTOM);
                keyBuilder.setCustomKid(protoKey.getCustomKid().getValue());
            }
            else {
                parametersBuilder.setKidStrategy(JwtRsaSsaPssParameters.KidStrategy.IGNORED);
            }
        }
        final BigInteger modulus = decodeBigInteger(protoKey.getN());
        final int modulusSizeInBits = modulus.bitLength();
        parametersBuilder.setAlgorithm(JwtRsaSsaPssProtoSerialization.ALGORITHM_CONVERTER.fromProtoEnum(protoKey.getAlgorithm())).setPublicExponent(decodeBigInteger(protoKey.getE())).setModulusSizeBits(modulusSizeInBits);
        keyBuilder.setModulus(modulus).setParameters(parametersBuilder.build());
        return keyBuilder.build();
    }
    
    private static JwtRsaSsaPssPublicKey parsePublicKey(final ProtoKeySerialization serialization, @Nullable final SecretKeyAccess access) throws GeneralSecurityException {
        if (!serialization.getTypeUrl().equals("type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey")) {
            throw new IllegalArgumentException("Wrong type URL in call to JwtRsaSsaPssProtoSerialization.parsePublicKey: " + serialization.getTypeUrl());
        }
        try {
            final com.google.crypto.tink.proto.JwtRsaSsaPssPublicKey protoKey = com.google.crypto.tink.proto.JwtRsaSsaPssPublicKey.parseFrom(serialization.getValue(), ExtensionRegistryLite.getEmptyRegistry());
            return getPublicKeyFromProto(protoKey, serialization.getOutputPrefixType(), serialization.getIdRequirementOrNull());
        }
        catch (final InvalidProtocolBufferException e) {
            throw new GeneralSecurityException("Parsing JwtRsaSsaPssPublicKey failed");
        }
    }
    
    private static SecretBigInteger decodeSecretBigInteger(final ByteString data, final SecretKeyAccess access) {
        return SecretBigInteger.fromBigInteger(BigIntegerEncoding.fromUnsignedBigEndianBytes(data.toByteArray()), access);
    }
    
    private static JwtRsaSsaPssPrivateKey parsePrivateKey(final ProtoKeySerialization serialization, @Nullable final SecretKeyAccess access) throws GeneralSecurityException {
        if (!serialization.getTypeUrl().equals("type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey")) {
            throw new IllegalArgumentException("Wrong type URL in call to JwtRsaSsaPssProtoSerialization.parsePrivateKey: " + serialization.getTypeUrl());
        }
        try {
            final com.google.crypto.tink.proto.JwtRsaSsaPssPrivateKey protoKey = com.google.crypto.tink.proto.JwtRsaSsaPssPrivateKey.parseFrom(serialization.getValue(), ExtensionRegistryLite.getEmptyRegistry());
            validateVersion(protoKey.getVersion());
            final JwtRsaSsaPssPublicKey publicKey = getPublicKeyFromProto(protoKey.getPublicKey(), serialization.getOutputPrefixType(), serialization.getIdRequirementOrNull());
            final SecretKeyAccess a = SecretKeyAccess.requireAccess(access);
            return JwtRsaSsaPssPrivateKey.builder().setPublicKey(publicKey).setPrimes(decodeSecretBigInteger(protoKey.getP(), a), decodeSecretBigInteger(protoKey.getQ(), a)).setPrivateExponent(decodeSecretBigInteger(protoKey.getD(), a)).setPrimeExponents(decodeSecretBigInteger(protoKey.getDp(), a), decodeSecretBigInteger(protoKey.getDq(), a)).setCrtCoefficient(decodeSecretBigInteger(protoKey.getCrt(), a)).build();
        }
        catch (final InvalidProtocolBufferException e) {
            throw new GeneralSecurityException("Parsing JwtRsaSsaPssPrivateKey failed");
        }
    }
    
    public static void register() throws GeneralSecurityException {
        register(MutableSerializationRegistry.globalInstance());
    }
    
    public static void register(final MutableSerializationRegistry registry) throws GeneralSecurityException {
        registry.registerParametersSerializer(JwtRsaSsaPssProtoSerialization.PARAMETERS_SERIALIZER);
        registry.registerParametersParser(JwtRsaSsaPssProtoSerialization.PARAMETERS_PARSER);
        registry.registerKeySerializer(JwtRsaSsaPssProtoSerialization.PUBLIC_KEY_SERIALIZER);
        registry.registerKeyParser(JwtRsaSsaPssProtoSerialization.PUBLIC_KEY_PARSER);
        registry.registerKeySerializer(JwtRsaSsaPssProtoSerialization.PRIVATE_KEY_SERIALIZER);
        registry.registerKeyParser(JwtRsaSsaPssProtoSerialization.PRIVATE_KEY_PARSER);
    }
    
    private JwtRsaSsaPssProtoSerialization() {
    }
    
    static {
        PRIVATE_TYPE_URL_BYTES = Util.toBytesFromPrintableAscii("type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPrivateKey");
        PUBLIC_TYPE_URL_BYTES = Util.toBytesFromPrintableAscii("type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey");
        PARAMETERS_SERIALIZER = ParametersSerializer.create(JwtRsaSsaPssProtoSerialization::serializeParameters, JwtRsaSsaPssParameters.class, ProtoParametersSerialization.class);
        PARAMETERS_PARSER = ParametersParser.create(JwtRsaSsaPssProtoSerialization::parseParameters, JwtRsaSsaPssProtoSerialization.PRIVATE_TYPE_URL_BYTES, ProtoParametersSerialization.class);
        PUBLIC_KEY_SERIALIZER = KeySerializer.create(JwtRsaSsaPssProtoSerialization::serializePublicKey, JwtRsaSsaPssPublicKey.class, ProtoKeySerialization.class);
        PUBLIC_KEY_PARSER = KeyParser.create(JwtRsaSsaPssProtoSerialization::parsePublicKey, JwtRsaSsaPssProtoSerialization.PUBLIC_TYPE_URL_BYTES, ProtoKeySerialization.class);
        PRIVATE_KEY_SERIALIZER = KeySerializer.create(JwtRsaSsaPssProtoSerialization::serializePrivateKey, JwtRsaSsaPssPrivateKey.class, ProtoKeySerialization.class);
        PRIVATE_KEY_PARSER = KeyParser.create(JwtRsaSsaPssProtoSerialization::parsePrivateKey, JwtRsaSsaPssProtoSerialization.PRIVATE_TYPE_URL_BYTES, ProtoKeySerialization.class);
        ALGORITHM_CONVERTER = EnumTypeProtoConverter.builder().add(JwtRsaSsaPssAlgorithm.PS256, JwtRsaSsaPssParameters.Algorithm.PS256).add(JwtRsaSsaPssAlgorithm.PS384, JwtRsaSsaPssParameters.Algorithm.PS384).add(JwtRsaSsaPssAlgorithm.PS512, JwtRsaSsaPssParameters.Algorithm.PS512).build();
    }
}
