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

package com.google.crypto.tink.hybrid;

import com.google.crypto.tink.Parameters;
import com.google.crypto.tink.Key;
import com.google.errorprone.annotations.RestrictedApi;
import com.google.crypto.tink.AccessesPartialKey;
import com.google.crypto.tink.InsecureSecretKeyAccess;
import java.util.Arrays;
import com.google.crypto.tink.subtle.X25519;
import com.google.crypto.tink.internal.EllipticCurvesUtil;
import java.security.GeneralSecurityException;
import java.security.spec.ECPoint;
import java.math.BigInteger;
import com.google.crypto.tink.subtle.EllipticCurves;
import java.security.spec.ECParameterSpec;
import com.google.crypto.tink.util.SecretBytes;
import javax.annotation.Nullable;
import com.google.crypto.tink.util.SecretBigInteger;
import com.google.errorprone.annotations.Immutable;

@Immutable
public final class EciesPrivateKey extends HybridPrivateKey
{
    private final EciesPublicKey publicKey;
    @Nullable
    private final SecretBigInteger nistPrivateKeyValue;
    @Nullable
    private final SecretBytes x25519PrivateKeyBytes;
    
    private EciesPrivateKey(final EciesPublicKey publicKey, @Nullable final SecretBigInteger nistPrivateKeyValue, @Nullable final SecretBytes x25519PrivateKeyBytes) {
        this.publicKey = publicKey;
        this.nistPrivateKeyValue = nistPrivateKeyValue;
        this.x25519PrivateKeyBytes = x25519PrivateKeyBytes;
    }
    
    private static ECParameterSpec toParameterSpecNistCurve(final EciesParameters.CurveType curveType) {
        if (curveType == EciesParameters.CurveType.NIST_P256) {
            return EllipticCurves.getNistP256Params();
        }
        if (curveType == EciesParameters.CurveType.NIST_P384) {
            return EllipticCurves.getNistP384Params();
        }
        if (curveType == EciesParameters.CurveType.NIST_P521) {
            return EllipticCurves.getNistP521Params();
        }
        throw new IllegalArgumentException("Unable to determine NIST curve type for " + curveType);
    }
    
    private static void validateNistPrivateKeyValue(final BigInteger privateValue, final ECPoint publicPoint, final EciesParameters.CurveType curveType) throws GeneralSecurityException {
        final BigInteger order = toParameterSpecNistCurve(curveType).getOrder();
        if (privateValue.signum() <= 0 || privateValue.compareTo(order) >= 0) {
            throw new GeneralSecurityException("Invalid private value");
        }
        final ECPoint p = EllipticCurvesUtil.multiplyByGenerator(privateValue, toParameterSpecNistCurve(curveType));
        if (!p.equals(publicPoint)) {
            throw new GeneralSecurityException("Invalid private value");
        }
    }
    
    private static void validateX25519PrivateKeyBytes(final byte[] privateKeyBytes, final byte[] publicKeyBytes) throws GeneralSecurityException {
        if (privateKeyBytes.length != 32) {
            throw new GeneralSecurityException("Private key bytes length for X25519 curve must be 32");
        }
        final byte[] expectedPublicKeyBytes = X25519.publicFromPrivate(privateKeyBytes);
        if (!Arrays.equals(expectedPublicKeyBytes, publicKeyBytes)) {
            throw new GeneralSecurityException("Invalid private key for public key.");
        }
    }
    
    @AccessesPartialKey
    @RestrictedApi(explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey", link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys", allowedOnPath = ".*Test\\.java", allowlistAnnotations = { AccessesPartialKey.class })
    public static EciesPrivateKey createForCurveX25519(final EciesPublicKey publicKey, final SecretBytes x25519PrivateKeyBytes) throws GeneralSecurityException {
        if (publicKey == null) {
            throw new GeneralSecurityException("ECIES private key cannot be constructed without an ECIES public key");
        }
        if (publicKey.getX25519CurvePointBytes() == null) {
            throw new GeneralSecurityException("ECIES private key for X25519 curve cannot be constructed with NIST-curve public key");
        }
        if (x25519PrivateKeyBytes == null) {
            throw new GeneralSecurityException("ECIES private key cannot be constructed without secret");
        }
        validateX25519PrivateKeyBytes(x25519PrivateKeyBytes.toByteArray(InsecureSecretKeyAccess.get()), publicKey.getX25519CurvePointBytes().toByteArray());
        return new EciesPrivateKey(publicKey, null, x25519PrivateKeyBytes);
    }
    
    @AccessesPartialKey
    @RestrictedApi(explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey", link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys", allowedOnPath = ".*Test\\.java", allowlistAnnotations = { AccessesPartialKey.class })
    public static EciesPrivateKey createForNistCurve(final EciesPublicKey publicKey, final SecretBigInteger nistPrivateKeyValue) throws GeneralSecurityException {
        if (publicKey == null) {
            throw new GeneralSecurityException("ECIES private key cannot be constructed without an ECIES public key");
        }
        if (publicKey.getNistCurvePoint() == null) {
            throw new GeneralSecurityException("ECIES private key for NIST curve cannot be constructed with X25519-curve public key");
        }
        if (nistPrivateKeyValue == null) {
            throw new GeneralSecurityException("ECIES private key cannot be constructed without secret");
        }
        validateNistPrivateKeyValue(nistPrivateKeyValue.getBigInteger(InsecureSecretKeyAccess.get()), publicKey.getNistCurvePoint(), publicKey.getParameters().getCurveType());
        return new EciesPrivateKey(publicKey, nistPrivateKeyValue, null);
    }
    
    @Nullable
    @RestrictedApi(explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey", link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys", allowedOnPath = ".*Test\\.java", allowlistAnnotations = { AccessesPartialKey.class })
    public SecretBytes getX25519PrivateKeyBytes() {
        return this.x25519PrivateKeyBytes;
    }
    
    @Nullable
    @RestrictedApi(explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey", link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys", allowedOnPath = ".*Test\\.java", allowlistAnnotations = { AccessesPartialKey.class })
    public SecretBigInteger getNistPrivateKeyValue() {
        return this.nistPrivateKeyValue;
    }
    
    @Override
    public EciesParameters getParameters() {
        return this.publicKey.getParameters();
    }
    
    @Override
    public EciesPublicKey getPublicKey() {
        return this.publicKey;
    }
    
    @Override
    public boolean equalsKey(final Key o) {
        if (!(o instanceof EciesPrivateKey)) {
            return false;
        }
        final EciesPrivateKey other = (EciesPrivateKey)o;
        if (!this.publicKey.equalsKey(other.publicKey)) {
            return false;
        }
        if (this.x25519PrivateKeyBytes == null && other.x25519PrivateKeyBytes == null) {
            return this.nistPrivateKeyValue.equalsSecretBigInteger(other.nistPrivateKeyValue);
        }
        return this.x25519PrivateKeyBytes.equalsSecretBytes(other.x25519PrivateKeyBytes);
    }
}
