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

package org.bouncycastle.pqc.crypto.mayo;

import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Longs;
import org.bouncycastle.util.GF16;
import org.bouncycastle.crypto.digests.SHAKEDigest;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.KeyGenerationParameters;
import java.security.SecureRandom;
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;

public class MayoKeyPairGenerator implements AsymmetricCipherKeyPairGenerator
{
    private MayoParameters p;
    private SecureRandom random;
    
    @Override
    public void init(final KeyGenerationParameters keyGenerationParameters) {
        this.p = ((MayoKeyGenerationParameters)keyGenerationParameters).getParameters();
        this.random = keyGenerationParameters.getRandom();
    }
    
    @Override
    public AsymmetricCipherKeyPair generateKeyPair() {
        final int mVecLimbs = this.p.getMVecLimbs();
        final int m = this.p.getM();
        final int v = this.p.getV();
        final int o = this.p.getO();
        final int oBytes = this.p.getOBytes();
        final int p1Limbs = this.p.getP1Limbs();
        final int p3Limbs = this.p.getP3Limbs();
        final int pkSeedBytes = this.p.getPkSeedBytes();
        final int skSeedBytes = this.p.getSkSeedBytes();
        final byte[] array = new byte[this.p.getCpkBytes()];
        final byte[] bytes = new byte[this.p.getCskBytes()];
        final byte[] array2 = new byte[pkSeedBytes + oBytes];
        final long[] array3 = new long[p1Limbs + this.p.getP2Limbs()];
        final long[] array4 = new long[o * o * mVecLimbs];
        final byte[] array5 = new byte[v * o];
        this.random.nextBytes(bytes);
        final SHAKEDigest shakeDigest = new SHAKEDigest(256);
        shakeDigest.update(bytes, 0, skSeedBytes);
        shakeDigest.doFinal(array2, 0, pkSeedBytes + oBytes);
        GF16.decode(array2, pkSeedBytes, array5, 0, array5.length);
        Utils.expandP1P2(this.p, array3, array2);
        GF16Utils.mulAddMUpperTriangularMatXMat(mVecLimbs, array3, array5, array3, p1Limbs, v, o);
        GF16Utils.mulAddMatTransXMMat(mVecLimbs, array5, array3, p1Limbs, array4, v, o);
        System.arraycopy(array2, 0, array, 0, pkSeedBytes);
        final long[] array6 = new long[p3Limbs];
        int n = 0;
        for (int n2 = o * mVecLimbs, i = 0, n3 = 0, n4 = 0; i < o; ++i, n4 += n2, n3 += mVecLimbs) {
            for (int j = i, n5 = n3, n6 = n4; j < o; ++j, n5 += mVecLimbs, n6 += n2) {
                System.arraycopy(array4, n4 + n5, array6, n, mVecLimbs);
                if (i != j) {
                    Longs.xorTo(mVecLimbs, array4, n6 + n3, array6, n);
                }
                n += mVecLimbs;
            }
        }
        Utils.packMVecs(array6, array, pkSeedBytes, p3Limbs / mVecLimbs, m);
        Arrays.clear(array5);
        Arrays.clear(array4);
        return new AsymmetricCipherKeyPair(new MayoPublicKeyParameters(this.p, array), new MayoPrivateKeyParameters(this.p, bytes));
    }
}
