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

package com.google.crypto.tink.signature;

import java.math.BigInteger;
import com.google.crypto.tink.InsecureSecretKeyAccess;
import java.security.GeneralSecurityException;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import javax.annotation.Nullable;
import com.google.crypto.tink.Parameters;
import com.google.crypto.tink.Key;
import com.google.crypto.tink.AccessesPartialKey;
import com.google.errorprone.annotations.RestrictedApi;
import com.google.crypto.tink.util.SecretBigInteger;

public final class RsaSsaPkcs1PrivateKey extends SignaturePrivateKey
{
    private final RsaSsaPkcs1PublicKey publicKey;
    private final SecretBigInteger d;
    private final SecretBigInteger p;
    private final SecretBigInteger q;
    private final SecretBigInteger dP;
    private final SecretBigInteger dQ;
    private final SecretBigInteger qInv;
    
    private RsaSsaPkcs1PrivateKey(final RsaSsaPkcs1PublicKey publicKey, final SecretBigInteger p, final SecretBigInteger q, final SecretBigInteger d, final SecretBigInteger dP, final SecretBigInteger dQ, final SecretBigInteger qInv) {
        this.publicKey = publicKey;
        this.p = p;
        this.q = q;
        this.d = d;
        this.dP = dP;
        this.dQ = dQ;
        this.qInv = qInv;
    }
    
    @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 Builder builder() {
        return new Builder();
    }
    
    @Override
    public RsaSsaPkcs1Parameters getParameters() {
        return this.publicKey.getParameters();
    }
    
    @Override
    public RsaSsaPkcs1PublicKey getPublicKey() {
        return this.publicKey;
    }
    
    @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 getPrimeP() {
        return this.p;
    }
    
    @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 getPrimeQ() {
        return this.q;
    }
    
    public SecretBigInteger getPrivateExponent() {
        return this.d;
    }
    
    public SecretBigInteger getPrimeExponentP() {
        return this.dP;
    }
    
    public SecretBigInteger getPrimeExponentQ() {
        return this.dQ;
    }
    
    public SecretBigInteger getCrtCoefficient() {
        return this.qInv;
    }
    
    @Override
    public boolean equalsKey(final Key o) {
        if (!(o instanceof RsaSsaPkcs1PrivateKey)) {
            return false;
        }
        final RsaSsaPkcs1PrivateKey that = (RsaSsaPkcs1PrivateKey)o;
        return that.publicKey.equalsKey(this.publicKey) && this.p.equalsSecretBigInteger(that.p) && this.q.equalsSecretBigInteger(that.q) && this.d.equalsSecretBigInteger(that.d) && this.dP.equalsSecretBigInteger(that.dP) && this.dQ.equalsSecretBigInteger(that.dQ) && this.qInv.equalsSecretBigInteger(that.qInv);
    }
    
    public static class Builder
    {
        @Nullable
        private RsaSsaPkcs1PublicKey publicKey;
        @Nullable
        private SecretBigInteger d;
        @Nullable
        private SecretBigInteger p;
        @Nullable
        private SecretBigInteger q;
        @Nullable
        private SecretBigInteger dP;
        @Nullable
        private SecretBigInteger dQ;
        @Nullable
        private SecretBigInteger qInv;
        private static final int PRIME_CERTAINTY = 10;
        
        private Builder() {
            this.publicKey = null;
            this.d = null;
            this.p = null;
            this.q = null;
            this.dP = null;
            this.dQ = null;
            this.qInv = null;
        }
        
        @CanIgnoreReturnValue
        public Builder setPublicKey(final RsaSsaPkcs1PublicKey publicKey) {
            this.publicKey = publicKey;
            return this;
        }
        
        @CanIgnoreReturnValue
        public Builder setPrimes(final SecretBigInteger p, final SecretBigInteger q) {
            this.p = p;
            this.q = q;
            return this;
        }
        
        @CanIgnoreReturnValue
        public Builder setPrivateExponent(final SecretBigInteger d) {
            this.d = d;
            return this;
        }
        
        @CanIgnoreReturnValue
        public Builder setPrimeExponents(final SecretBigInteger dP, final SecretBigInteger dQ) {
            this.dP = dP;
            this.dQ = dQ;
            return this;
        }
        
        @CanIgnoreReturnValue
        public Builder setCrtCoefficient(final SecretBigInteger qInv) {
            this.qInv = qInv;
            return this;
        }
        
        @AccessesPartialKey
        public RsaSsaPkcs1PrivateKey build() throws GeneralSecurityException {
            if (this.publicKey == null) {
                throw new GeneralSecurityException("Cannot build without a RSA SSA PKCS1 public key");
            }
            if (this.p == null || this.q == null) {
                throw new GeneralSecurityException("Cannot build without prime factors");
            }
            if (this.d == null) {
                throw new GeneralSecurityException("Cannot build without private exponent");
            }
            if (this.dP == null || this.dQ == null) {
                throw new GeneralSecurityException("Cannot build without prime exponents");
            }
            if (this.qInv == null) {
                throw new GeneralSecurityException("Cannot build without CRT coefficient");
            }
            final BigInteger e = this.publicKey.getParameters().getPublicExponent();
            final BigInteger n = this.publicKey.getModulus();
            final BigInteger ip = this.p.getBigInteger(InsecureSecretKeyAccess.get());
            final BigInteger iq = this.q.getBigInteger(InsecureSecretKeyAccess.get());
            final BigInteger id = this.d.getBigInteger(InsecureSecretKeyAccess.get());
            final BigInteger idP = this.dP.getBigInteger(InsecureSecretKeyAccess.get());
            final BigInteger idQ = this.dQ.getBigInteger(InsecureSecretKeyAccess.get());
            final BigInteger iqInv = this.qInv.getBigInteger(InsecureSecretKeyAccess.get());
            if (!ip.isProbablePrime(10)) {
                throw new GeneralSecurityException("p is not a prime");
            }
            if (!iq.isProbablePrime(10)) {
                throw new GeneralSecurityException("q is not a prime");
            }
            if (!ip.multiply(iq).equals(n)) {
                throw new GeneralSecurityException("Prime p times prime q is not equal to the public key's modulus");
            }
            final BigInteger pMinusOne = ip.subtract(BigInteger.ONE);
            final BigInteger qMinusOne = iq.subtract(BigInteger.ONE);
            final BigInteger lambda = pMinusOne.divide(pMinusOne.gcd(qMinusOne)).multiply(qMinusOne);
            if (!e.multiply(id).mod(lambda).equals(BigInteger.ONE)) {
                throw new GeneralSecurityException("D is invalid.");
            }
            if (!e.multiply(idP).mod(pMinusOne).equals(BigInteger.ONE)) {
                throw new GeneralSecurityException("dP is invalid.");
            }
            if (!e.multiply(idQ).mod(qMinusOne).equals(BigInteger.ONE)) {
                throw new GeneralSecurityException("dQ is invalid.");
            }
            if (!iq.multiply(iqInv).mod(ip).equals(BigInteger.ONE)) {
                throw new GeneralSecurityException("qInv is invalid.");
            }
            return new RsaSsaPkcs1PrivateKey(this.publicKey, this.p, this.q, this.d, this.dP, this.dQ, this.qInv, null);
        }
    }
}
