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

package org.bouncycastle.pqc.crypto.ntru;

import org.bouncycastle.pqc.math.ntru.HPSPolynomial;
import org.bouncycastle.pqc.math.ntru.parameters.NTRUHPSParameterSet;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.pqc.math.ntru.Polynomial;
import org.bouncycastle.pqc.math.ntru.parameters.NTRUHRSSParameterSet;
import org.bouncycastle.pqc.math.ntru.parameters.NTRUParameterSet;

class NTRUOWCPA
{
    private final NTRUParameterSet params;
    private final NTRUSampling sampling;
    
    public NTRUOWCPA(final NTRUParameterSet params) {
        this.params = params;
        this.sampling = new NTRUSampling(params);
    }
    
    public OWCPAKeyPair keypair(final byte[] array) {
        final byte[] array2 = new byte[this.params.owcpaSecretKeyBytes()];
        final int n = this.params.n();
        this.params.q();
        final Polynomial polynomial = this.params.createPolynomial();
        final Polynomial polynomial2 = this.params.createPolynomial();
        final Polynomial polynomial3 = this.params.createPolynomial();
        final Polynomial polynomial4 = polynomial;
        final Polynomial polynomial5 = polynomial;
        final Polynomial polynomial6 = polynomial2;
        final Polynomial polynomial7 = polynomial3;
        final Polynomial polynomial8 = polynomial;
        final Polynomial polynomial9 = polynomial;
        final PolynomialPair sampleFg = this.sampling.sampleFg(array);
        final Polynomial f = sampleFg.f();
        final Polynomial g = sampleFg.g();
        polynomial4.s3Inv(f);
        f.s3ToBytes(array2, 0);
        polynomial4.s3ToBytes(array2, this.params.packTrinaryBytes());
        f.z3ToZq();
        g.z3ToZq();
        if (this.params instanceof NTRUHRSSParameterSet) {
            for (int i = n - 1; i > 0; --i) {
                g.coeffs[i] = (short)(3 * (g.coeffs[i - 1] - g.coeffs[i]));
            }
            g.coeffs[0] = (short)(-(3 * g.coeffs[0]));
        }
        else {
            for (int j = 0; j < n; ++j) {
                g.coeffs[j] *= 3;
            }
        }
        polynomial5.rqMul(g, f);
        polynomial6.rqInv(polynomial5);
        polynomial7.rqMul(polynomial6, f);
        polynomial8.sqMul(polynomial7, f);
        final byte[] sqToBytes = polynomial8.sqToBytes(array2.length - 2 * this.params.packTrinaryBytes());
        System.arraycopy(sqToBytes, 0, array2, 2 * this.params.packTrinaryBytes(), sqToBytes.length);
        polynomial7.rqMul(polynomial6, g);
        polynomial9.rqMul(polynomial7, g);
        return new OWCPAKeyPair(polynomial9.rqSumZeroToBytes(this.params.owcpaPublicKeyBytes()), array2);
    }
    
    public byte[] encrypt(final Polynomial polynomial, final Polynomial polynomial2, final byte[] array) {
        final Polynomial polynomial3 = this.params.createPolynomial();
        final Polynomial polynomial4 = this.params.createPolynomial();
        final Polynomial polynomial5 = polynomial3;
        final Polynomial polynomial6 = polynomial3;
        final Polynomial polynomial7 = polynomial4;
        polynomial5.rqSumZeroFromBytes(array);
        polynomial7.rqMul(polynomial, polynomial5);
        polynomial6.lift(polynomial2);
        for (int i = 0; i < this.params.n(); ++i) {
            final short[] coeffs = polynomial7.coeffs;
            final int n = i;
            coeffs[n] += polynomial6.coeffs[i];
        }
        return polynomial7.rqSumZeroToBytes(this.params.ntruCiphertextBytes());
    }
    
    public OWCPADecryptResult decrypt(final byte[] array, final byte[] array2) {
        final byte[] array3 = new byte[this.params.owcpaMsgBytes()];
        final Polynomial polynomial = this.params.createPolynomial();
        final Polynomial polynomial2 = this.params.createPolynomial();
        final Polynomial polynomial3 = this.params.createPolynomial();
        final Polynomial polynomial4 = this.params.createPolynomial();
        final Polynomial polynomial5 = polynomial;
        final Polynomial polynomial6 = polynomial2;
        final Polynomial polynomial7 = polynomial3;
        final Polynomial polynomial8 = polynomial2;
        final Polynomial polynomial9 = polynomial3;
        final Polynomial polynomial10 = polynomial4;
        final Polynomial polynomial11 = polynomial2;
        final Polynomial polynomial12 = polynomial3;
        final Polynomial polynomial13 = polynomial4;
        final Polynomial polynomial14 = polynomial;
        polynomial5.rqSumZeroFromBytes(array);
        polynomial6.s3FromBytes(array2);
        polynomial6.z3ToZq();
        polynomial7.rqMul(polynomial5, polynomial6);
        polynomial8.rqToS3(polynomial7);
        polynomial9.s3FromBytes(Arrays.copyOfRange(array2, this.params.packTrinaryBytes(), array2.length));
        polynomial10.s3Mul(polynomial8, polynomial9);
        polynomial10.s3ToBytes(array3, this.params.packTrinaryBytes());
        int n = 0x0 | this.checkCiphertext(array);
        if (this.params instanceof NTRUHPSParameterSet) {
            n |= this.checkM((HPSPolynomial)polynomial10);
        }
        polynomial11.lift(polynomial10);
        for (int i = 0; i < this.params.n(); ++i) {
            polynomial14.coeffs[i] = (short)(polynomial5.coeffs[i] - polynomial11.coeffs[i]);
        }
        polynomial12.sqFromBytes(Arrays.copyOfRange(array2, 2 * this.params.packTrinaryBytes(), array2.length));
        polynomial13.sqMul(polynomial14, polynomial12);
        final int n2 = n | this.checkR(polynomial13);
        polynomial13.trinaryZqToZ3();
        polynomial13.s3ToBytes(array3, 0);
        return new OWCPADecryptResult(array3, n2);
    }
    
    private int checkCiphertext(final byte[] array) {
        return 0x1 & ~(short)(array[this.params.ntruCiphertextBytes() - 1] & 255 << 8 - (0x7 & this.params.logQ() * this.params.packDegree())) + 1 >>> 15;
    }
    
    private int checkR(final Polynomial polynomial) {
        int n = 0;
        for (int i = 0; i < this.params.n() - 1; ++i) {
            final short n2 = polynomial.coeffs[i];
            n = (n | (n2 + 1 & this.params.q() - 4) | (n2 + 2 & 0x4));
        }
        return 0x1 & ~(n | polynomial.coeffs[this.params.n() - 1]) + 1 >>> 31;
    }
    
    private int checkM(final HPSPolynomial hpsPolynomial) {
        final int n = 0;
        int n2 = 0;
        int n3 = 0;
        for (int i = 0; i < this.params.n() - 1; ++i) {
            n2 = (short)(n2 + (hpsPolynomial.coeffs[i] & 0x1));
            n3 = (short)(n3 + (hpsPolynomial.coeffs[i] & 0x2));
        }
        return 0x1 & ~(n | (n2 ^ n3 >>> 1) | (n3 ^ ((NTRUHPSParameterSet)this.params).weight())) + 1 >>> 31;
    }
}
