// 
// 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.crypto.tink.util.SecretBigInteger;
import com.google.crypto.tink.proto.KeyData;
import javax.annotation.Nullable;
import com.google.crypto.tink.SecretKeyAccess;
import java.security.spec.ECPoint;
import com.google.protobuf.ByteString;
import com.google.crypto.tink.internal.BigIntegerEncoding;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.ExtensionRegistryLite;
import com.google.crypto.tink.proto.KeyTemplate;
import com.google.crypto.tink.proto.OutputPrefixType;
import com.google.crypto.tink.proto.JwtEcdsaKeyFormat;
import java.security.GeneralSecurityException;
import com.google.crypto.tink.proto.JwtEcdsaAlgorithm;
import com.google.crypto.tink.jwt.JwtEcdsaPrivateKey;
import com.google.crypto.tink.internal.KeyParser;
import com.google.crypto.tink.internal.ProtoKeySerialization;
import com.google.crypto.tink.jwt.JwtEcdsaPublicKey;
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.JwtEcdsaParameters;
import com.google.crypto.tink.internal.ParametersSerializer;
import com.google.crypto.tink.util.Bytes;
import com.google.crypto.tink.AccessesPartialKey;

@AccessesPartialKey
public final class JwtEcdsaProtoSerialization
{
    private static final String TYPE_URL = "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey";
    private static final Bytes TYPE_URL_BYTES;
    private static final String PUBLIC_TYPE_URL = "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey";
    private static final Bytes PUBLIC_TYPE_URL_BYTES;
    private static final ParametersSerializer<JwtEcdsaParameters, ProtoParametersSerialization> PARAMETERS_SERIALIZER;
    private static final ParametersParser<ProtoParametersSerialization> PARAMETERS_PARSER;
    private static final KeySerializer<JwtEcdsaPublicKey, ProtoKeySerialization> PUBLIC_KEY_SERIALIZER;
    private static final KeyParser<ProtoKeySerialization> PUBLIC_KEY_PARSER;
    private static final KeySerializer<JwtEcdsaPrivateKey, ProtoKeySerialization> PRIVATE_KEY_SERIALIZER;
    private static final KeyParser<ProtoKeySerialization> PRIVATE_KEY_PARSER;
    
    private static JwtEcdsaAlgorithm toProtoAlgorithm(final JwtEcdsaParameters.Algorithm algorithm) throws GeneralSecurityException {
        if (JwtEcdsaParameters.Algorithm.ES256.equals(algorithm)) {
            return JwtEcdsaAlgorithm.ES256;
        }
        if (JwtEcdsaParameters.Algorithm.ES384.equals(algorithm)) {
            return JwtEcdsaAlgorithm.ES384;
        }
        if (JwtEcdsaParameters.Algorithm.ES512.equals(algorithm)) {
            return JwtEcdsaAlgorithm.ES512;
        }
        throw new GeneralSecurityException("Unable to serialize algorithm: " + algorithm);
    }
    
    private static JwtEcdsaParameters.Algorithm toAlgorithm(final JwtEcdsaAlgorithm algorithm) throws GeneralSecurityException {
        switch (algorithm) {
            case ES256: {
                return JwtEcdsaParameters.Algorithm.ES256;
            }
            case ES384: {
                return JwtEcdsaParameters.Algorithm.ES384;
            }
            case ES512: {
                return JwtEcdsaParameters.Algorithm.ES512;
            }
            default: {
                throw new GeneralSecurityException("Unable to parse algorithm: " + algorithm.getNumber());
            }
        }
    }
    
    private static JwtEcdsaKeyFormat serializeToJwtEcdsaKeyFormat(final JwtEcdsaParameters parameters) throws GeneralSecurityException {
        if (!parameters.getKidStrategy().equals(JwtEcdsaParameters.KidStrategy.IGNORED) && !parameters.getKidStrategy().equals(JwtEcdsaParameters.KidStrategy.BASE64_ENCODED_KEY_ID)) {
            throw new GeneralSecurityException("Unable to serialize Parameters object with KidStrategy " + parameters.getKidStrategy());
        }
        return JwtEcdsaKeyFormat.newBuilder().setVersion(0).setAlgorithm(toProtoAlgorithm(parameters.getAlgorithm())).build();
    }
    
    private static ProtoParametersSerialization serializeParameters(final JwtEcdsaParameters parameters) throws GeneralSecurityException {
        OutputPrefixType outputPrefixType = OutputPrefixType.TINK;
        if (parameters.getKidStrategy().equals(JwtEcdsaParameters.KidStrategy.IGNORED)) {
            outputPrefixType = OutputPrefixType.RAW;
        }
        return ProtoParametersSerialization.create(KeyTemplate.newBuilder().setTypeUrl("type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey").setValue(serializeToJwtEcdsaKeyFormat(parameters).toByteString()).setOutputPrefixType(outputPrefixType).build());
    }
    
    private static JwtEcdsaParameters parseParameters(final ProtoParametersSerialization serialization) throws GeneralSecurityException {
        if (!serialization.getKeyTemplate().getTypeUrl().equals("type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey")) {
            throw new IllegalArgumentException("Wrong type URL in call to JwtEcdsaParameters.parseParameters: " + serialization.getKeyTemplate().getTypeUrl());
        }
        JwtEcdsaKeyFormat format;
        try {
            format = JwtEcdsaKeyFormat.parseFrom(serialization.getKeyTemplate().getValue(), ExtensionRegistryLite.getEmptyRegistry());
        }
        catch (final InvalidProtocolBufferException e) {
            throw new GeneralSecurityException("Parsing JwtEcdsaKeyFormat failed: ", e);
        }
        if (format.getVersion() != 0) {
            throw new GeneralSecurityException("Parsing HmacParameters failed: unknown Version " + format.getVersion());
        }
        JwtEcdsaParameters.KidStrategy kidStrategy = null;
        if (serialization.getKeyTemplate().getOutputPrefixType().equals(OutputPrefixType.TINK)) {
            kidStrategy = JwtEcdsaParameters.KidStrategy.BASE64_ENCODED_KEY_ID;
        }
        if (serialization.getKeyTemplate().getOutputPrefixType().equals(OutputPrefixType.RAW)) {
            kidStrategy = JwtEcdsaParameters.KidStrategy.IGNORED;
        }
        if (kidStrategy == null) {
            throw new GeneralSecurityException("Invalid OutputPrefixType for JwtHmacKeyFormat");
        }
        return JwtEcdsaParameters.builder().setAlgorithm(toAlgorithm(format.getAlgorithm())).setKidStrategy(kidStrategy).build();
    }
    
    private static int getEncodingLength(final JwtEcdsaParameters.Algorithm algorithm) throws GeneralSecurityException {
        if (algorithm.equals(JwtEcdsaParameters.Algorithm.ES256)) {
            return 33;
        }
        if (algorithm.equals(JwtEcdsaParameters.Algorithm.ES384)) {
            return 49;
        }
        if (algorithm.equals(JwtEcdsaParameters.Algorithm.ES512)) {
            return 67;
        }
        throw new GeneralSecurityException("Unknown algorithm: " + algorithm);
    }
    
    private static OutputPrefixType toProtoOutputPrefixType(final JwtEcdsaParameters parameters) {
        if (parameters.getKidStrategy().equals(JwtEcdsaParameters.KidStrategy.BASE64_ENCODED_KEY_ID)) {
            return OutputPrefixType.TINK;
        }
        return OutputPrefixType.RAW;
    }
    
    private static com.google.crypto.tink.proto.JwtEcdsaPublicKey serializePublicKey(final JwtEcdsaPublicKey key) throws GeneralSecurityException {
        final int encLength = getEncodingLength(key.getParameters().getAlgorithm());
        final ECPoint publicPoint = key.getPublicPoint();
        final com.google.crypto.tink.proto.JwtEcdsaPublicKey.Builder builder = com.google.crypto.tink.proto.JwtEcdsaPublicKey.newBuilder().setVersion(0).setAlgorithm(toProtoAlgorithm(key.getParameters().getAlgorithm())).setX(ByteString.copyFrom(BigIntegerEncoding.toBigEndianBytesOfFixedLength(publicPoint.getAffineX(), encLength))).setY(ByteString.copyFrom(BigIntegerEncoding.toBigEndianBytesOfFixedLength(publicPoint.getAffineY(), encLength)));
        if (key.getParameters().getKidStrategy().equals(JwtEcdsaParameters.KidStrategy.CUSTOM)) {
            builder.setCustomKid(com.google.crypto.tink.proto.JwtEcdsaPublicKey.CustomKid.newBuilder().setValue(key.getKid().get()).build());
        }
        return builder.build();
    }
    
    private static ProtoKeySerialization serializePublicKey(final JwtEcdsaPublicKey key, @Nullable final SecretKeyAccess access) throws GeneralSecurityException {
        return ProtoKeySerialization.create("type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey", serializePublicKey(key).toByteString(), KeyData.KeyMaterialType.ASYMMETRIC_PUBLIC, toProtoOutputPrefixType(key.getParameters()), key.getIdRequirementOrNull());
    }
    
    private static JwtEcdsaPublicKey parsePublicKeyFromProto(final com.google.crypto.tink.proto.JwtEcdsaPublicKey protoKey, final OutputPrefixType outputPrefixType, @Nullable final Integer idRequirement) throws GeneralSecurityException {
        if (protoKey.getVersion() != 0) {
            throw new GeneralSecurityException("Only version 0 keys are accepted");
        }
        final JwtEcdsaParameters.Builder parametersBuilder = JwtEcdsaParameters.builder();
        final JwtEcdsaPublicKey.Builder keyBuilder = JwtEcdsaPublicKey.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(JwtEcdsaParameters.KidStrategy.BASE64_ENCODED_KEY_ID);
            keyBuilder.setIdRequirement(idRequirement);
        }
        else if (outputPrefixType.equals(OutputPrefixType.RAW)) {
            if (protoKey.hasCustomKid()) {
                parametersBuilder.setKidStrategy(JwtEcdsaParameters.KidStrategy.CUSTOM);
                keyBuilder.setCustomKid(protoKey.getCustomKid().getValue());
            }
            else {
                parametersBuilder.setKidStrategy(JwtEcdsaParameters.KidStrategy.IGNORED);
            }
        }
        parametersBuilder.setAlgorithm(toAlgorithm(protoKey.getAlgorithm()));
        keyBuilder.setPublicPoint(new ECPoint(BigIntegerEncoding.fromUnsignedBigEndianBytes(protoKey.getX().toByteArray()), BigIntegerEncoding.fromUnsignedBigEndianBytes(protoKey.getY().toByteArray())));
        return keyBuilder.setParameters(parametersBuilder.build()).build();
    }
    
    private static JwtEcdsaPublicKey parsePublicKey(final ProtoKeySerialization serialization, @Nullable final SecretKeyAccess access) throws GeneralSecurityException {
        if (!serialization.getTypeUrl().equals("type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey")) {
            throw new IllegalArgumentException("Wrong type URL in call to EcdsaProtoSerialization.parsePublicKey: " + serialization.getTypeUrl());
        }
        try {
            final com.google.crypto.tink.proto.JwtEcdsaPublicKey protoKey = com.google.crypto.tink.proto.JwtEcdsaPublicKey.parseFrom(serialization.getValue(), ExtensionRegistryLite.getEmptyRegistry());
            return parsePublicKeyFromProto(protoKey, serialization.getOutputPrefixType(), serialization.getIdRequirementOrNull());
        }
        catch (final InvalidProtocolBufferException e) {
            throw new GeneralSecurityException("Parsing EcdsaPublicKey failed");
        }
    }
    
    private static com.google.crypto.tink.proto.JwtEcdsaPrivateKey serializePrivateKeyToProto(final JwtEcdsaPrivateKey key, final SecretKeyAccess access) throws GeneralSecurityException {
        final int encLength = getEncodingLength(key.getParameters().getAlgorithm());
        return com.google.crypto.tink.proto.JwtEcdsaPrivateKey.newBuilder().setPublicKey(serializePublicKey(key.getPublicKey())).setKeyValue(ByteString.copyFrom(BigIntegerEncoding.toBigEndianBytesOfFixedLength(key.getPrivateValue().getBigInteger(access), encLength))).build();
    }
    
    private static ProtoKeySerialization serializePrivateKey(final JwtEcdsaPrivateKey key, @Nullable final SecretKeyAccess access) throws GeneralSecurityException {
        return ProtoKeySerialization.create("type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey", serializePrivateKeyToProto(key, SecretKeyAccess.requireAccess(access)).toByteString(), KeyData.KeyMaterialType.ASYMMETRIC_PRIVATE, toProtoOutputPrefixType(key.getParameters()), key.getIdRequirementOrNull());
    }
    
    private static JwtEcdsaPrivateKey parsePrivateKey(final ProtoKeySerialization serialization, @Nullable final SecretKeyAccess access) throws GeneralSecurityException {
        if (!serialization.getTypeUrl().equals("type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey")) {
            throw new IllegalArgumentException("Wrong type URL in call to EcdsaProtoSerialization.parsePublicKey: " + serialization.getTypeUrl());
        }
        try {
            final com.google.crypto.tink.proto.JwtEcdsaPrivateKey protoKey = com.google.crypto.tink.proto.JwtEcdsaPrivateKey.parseFrom(serialization.getValue(), ExtensionRegistryLite.getEmptyRegistry());
            if (protoKey.getVersion() != 0) {
                throw new GeneralSecurityException("Only version 0 keys are accepted");
            }
            final JwtEcdsaPublicKey publicKey = parsePublicKeyFromProto(protoKey.getPublicKey(), serialization.getOutputPrefixType(), serialization.getIdRequirementOrNull());
            return JwtEcdsaPrivateKey.create(publicKey, SecretBigInteger.fromBigInteger(BigIntegerEncoding.fromUnsignedBigEndianBytes(protoKey.getKeyValue().toByteArray()), SecretKeyAccess.requireAccess(access)));
        }
        catch (final InvalidProtocolBufferException e) {
            throw new GeneralSecurityException("Parsing EcdsaPrivateKey failed");
        }
    }
    
    public static void register() throws GeneralSecurityException {
        register(MutableSerializationRegistry.globalInstance());
    }
    
    public static void register(final MutableSerializationRegistry registry) throws GeneralSecurityException {
        registry.registerParametersSerializer(JwtEcdsaProtoSerialization.PARAMETERS_SERIALIZER);
        registry.registerParametersParser(JwtEcdsaProtoSerialization.PARAMETERS_PARSER);
        registry.registerKeySerializer(JwtEcdsaProtoSerialization.PUBLIC_KEY_SERIALIZER);
        registry.registerKeyParser(JwtEcdsaProtoSerialization.PUBLIC_KEY_PARSER);
        registry.registerKeySerializer(JwtEcdsaProtoSerialization.PRIVATE_KEY_SERIALIZER);
        registry.registerKeyParser(JwtEcdsaProtoSerialization.PRIVATE_KEY_PARSER);
    }
    
    private JwtEcdsaProtoSerialization() {
    }
    
    static {
        TYPE_URL_BYTES = Util.toBytesFromPrintableAscii("type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey");
        PUBLIC_TYPE_URL_BYTES = Util.toBytesFromPrintableAscii("type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey");
        PARAMETERS_SERIALIZER = ParametersSerializer.create(JwtEcdsaProtoSerialization::serializeParameters, JwtEcdsaParameters.class, ProtoParametersSerialization.class);
        PARAMETERS_PARSER = ParametersParser.create(JwtEcdsaProtoSerialization::parseParameters, JwtEcdsaProtoSerialization.TYPE_URL_BYTES, ProtoParametersSerialization.class);
        PUBLIC_KEY_SERIALIZER = KeySerializer.create(JwtEcdsaProtoSerialization::serializePublicKey, JwtEcdsaPublicKey.class, ProtoKeySerialization.class);
        PUBLIC_KEY_PARSER = KeyParser.create(JwtEcdsaProtoSerialization::parsePublicKey, JwtEcdsaProtoSerialization.PUBLIC_TYPE_URL_BYTES, ProtoKeySerialization.class);
        PRIVATE_KEY_SERIALIZER = KeySerializer.create(JwtEcdsaProtoSerialization::serializePrivateKey, JwtEcdsaPrivateKey.class, ProtoKeySerialization.class);
        PRIVATE_KEY_PARSER = KeyParser.create(JwtEcdsaProtoSerialization::parsePrivateKey, JwtEcdsaProtoSerialization.TYPE_URL_BYTES, ProtoKeySerialization.class);
    }
}
