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

package org.bouncycastle.pqc.crypto.lms;

import org.bouncycastle.util.Arrays;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.util.Pack;

class LM_OTS
{
    private static final short D_PBLC = -32640;
    private static final int ITER_K = 20;
    private static final int ITER_PREV = 23;
    private static final int ITER_J = 22;
    static final int SEED_RANDOMISER_INDEX = -3;
    static final int MAX_HASH = 32;
    static final short D_MESG = -32383;
    
    public static int coef(final byte[] array, final int n, final int n2) {
        return array[n * n2 / 8] >>> n2 * (~n & 8 / n2 - 1) & (1 << n2) - 1;
    }
    
    public static int cksm(final byte[] array, final int n, final LMOtsParameters lmOtsParameters) {
        int n2 = 0;
        final int n3 = (1 << lmOtsParameters.getW()) - 1;
        for (int i = 0; i < n * 8 / lmOtsParameters.getW(); ++i) {
            n2 = n2 + n3 - coef(array, i, lmOtsParameters.getW());
        }
        return n2 << lmOtsParameters.getLs();
    }
    
    public static LMOtsPublicKey lms_ots_generatePublicKey(final LMOtsPrivateKey lmOtsPrivateKey) {
        return new LMOtsPublicKey(lmOtsPrivateKey.getParameter(), lmOtsPrivateKey.getI(), lmOtsPrivateKey.getQ(), lms_ots_generatePublicKey(lmOtsPrivateKey.getParameter(), lmOtsPrivateKey.getI(), lmOtsPrivateKey.getQ(), lmOtsPrivateKey.getMasterSecret()));
    }
    
    static byte[] lms_ots_generatePublicKey(final LMOtsParameters lmOtsParameters, final byte[] array, final int q, final byte[] array2) {
        final Digest digest = DigestUtil.getDigest(lmOtsParameters);
        final byte[] build = Composer.compose().bytes(array).u32str(q).u16str(-32640).padUntil(0, 22).build();
        digest.update(build, 0, build.length);
        final Digest digest2 = DigestUtil.getDigest(lmOtsParameters);
        final byte[] build2 = Composer.compose().bytes(array).u32str(q).padUntil(0, 23 + digest2.getDigestSize()).build();
        final SeedDerive seedDerive = new SeedDerive(array, array2, DigestUtil.getDigest(lmOtsParameters));
        seedDerive.setQ(q);
        seedDerive.setJ(0);
        final int p4 = lmOtsParameters.getP();
        final int n = lmOtsParameters.getN();
        final int n2 = (1 << lmOtsParameters.getW()) - 1;
        for (int i = 0; i < p4; ++i) {
            seedDerive.deriveSeed(build2, i < p4 - 1, 23);
            Pack.shortToBigEndian((short)i, build2, 20);
            for (int j = 0; j < n2; ++j) {
                build2[22] = (byte)j;
                digest2.update(build2, 0, build2.length);
                digest2.doFinal(build2, 23);
            }
            digest.update(build2, 23, n);
        }
        final byte[] array3 = new byte[digest.getDigestSize()];
        digest.doFinal(array3, 0);
        return array3;
    }
    
    public static LMOtsSignature lm_ots_generate_signature(final LMSigParameters lmSigParameters, final LMOtsPrivateKey lmOtsPrivateKey, final byte[][] array, final byte[] array2, final boolean b) {
        byte[] q = new byte[34];
        byte[] c;
        if (!b) {
            final LMSContext signatureContext = lmOtsPrivateKey.getSignatureContext(lmSigParameters, array);
            LmsUtils.byteArray(array2, 0, array2.length, signatureContext);
            c = signatureContext.getC();
            q = signatureContext.getQ();
        }
        else {
            final int n = lmOtsPrivateKey.getParameter().getN();
            c = new byte[n];
            System.arraycopy(array2, 0, q, 0, n);
        }
        return lm_ots_generate_signature(lmOtsPrivateKey, q, c);
    }
    
    public static LMOtsSignature lm_ots_generate_signature(final LMOtsPrivateKey lmOtsPrivateKey, final byte[] array, final byte[] array2) {
        final LMOtsParameters parameter = lmOtsPrivateKey.getParameter();
        final int n = parameter.getN();
        final int p3 = parameter.getP();
        final int w = parameter.getW();
        final byte[] array3 = new byte[p3 * n];
        final Digest digest = DigestUtil.getDigest(parameter);
        final SeedDerive derivationFunction = lmOtsPrivateKey.getDerivationFunction();
        final int cksm = cksm(array, n, parameter);
        array[n] = (byte)(cksm >>> 8 & 0xFF);
        array[n + 1] = (byte)cksm;
        final byte[] build = Composer.compose().bytes(lmOtsPrivateKey.getI()).u32str(lmOtsPrivateKey.getQ()).padUntil(0, 23 + n).build();
        derivationFunction.setJ(0);
        for (int i = 0; i < p3; ++i) {
            Pack.shortToBigEndian((short)i, build, 20);
            derivationFunction.deriveSeed(build, i < p3 - 1, 23);
            for (int coef = coef(array, i, w), j = 0; j < coef; ++j) {
                build[22] = (byte)j;
                digest.update(build, 0, 23 + n);
                digest.doFinal(build, 23);
            }
            System.arraycopy(build, 23, array3, n * i, n);
        }
        return new LMOtsSignature(parameter, array2, array3);
    }
    
    public static boolean lm_ots_validate_signature(final LMOtsPublicKey lmOtsPublicKey, final LMOtsSignature lmOtsSignature, final byte[] array, final boolean b) throws LMSException {
        if (!lmOtsSignature.getType().equals(lmOtsPublicKey.getParameter())) {
            throw new LMSException("public key and signature ots types do not match");
        }
        return Arrays.areEqual(lm_ots_validate_signature_calculate(lmOtsPublicKey, lmOtsSignature, array), lmOtsPublicKey.getK());
    }
    
    public static byte[] lm_ots_validate_signature_calculate(final LMOtsPublicKey lmOtsPublicKey, final LMOtsSignature lmOtsSignature, final byte[] array) {
        final LMSContext otsContext = lmOtsPublicKey.createOtsContext(lmOtsSignature);
        LmsUtils.byteArray(array, otsContext);
        return lm_ots_validate_signature_calculate(otsContext);
    }
    
    public static byte[] lm_ots_validate_signature_calculate(final LMSContext lmsContext) {
        final LMOtsPublicKey publicKey = lmsContext.getPublicKey();
        final LMOtsParameters parameter = publicKey.getParameter();
        final Object signature = lmsContext.getSignature();
        LMOtsSignature otsSignature;
        if (signature instanceof LMSSignature) {
            otsSignature = ((LMSSignature)signature).getOtsSignature();
        }
        else {
            otsSignature = (LMOtsSignature)signature;
        }
        final int n = parameter.getN();
        final int w = parameter.getW();
        final int p = parameter.getP();
        final byte[] q = lmsContext.getQ();
        final int cksm = cksm(q, n, parameter);
        q[n] = (byte)(cksm >>> 8 & 0xFF);
        q[n + 1] = (byte)cksm;
        final byte[] i = publicKey.getI();
        final int q2 = publicKey.getQ();
        final Digest digest = DigestUtil.getDigest(parameter);
        LmsUtils.byteArray(i, digest);
        LmsUtils.u32str(q2, digest);
        LmsUtils.u16str((short)(-32640), digest);
        final byte[] build = Composer.compose().bytes(i).u32str(q2).padUntil(0, 23 + n).build();
        final int n2 = (1 << w) - 1;
        final byte[] y = otsSignature.getY();
        final Digest digest2 = DigestUtil.getDigest(parameter);
        for (int j = 0; j < p; ++j) {
            Pack.shortToBigEndian((short)j, build, 20);
            System.arraycopy(y, j * n, build, 23, n);
            for (int k = coef(q, j, w); k < n2; ++k) {
                build[22] = (byte)k;
                digest2.update(build, 0, 23 + n);
                digest2.doFinal(build, 23);
            }
            digest.update(build, 23, n);
        }
        final byte[] array = new byte[n];
        digest.doFinal(array, 0);
        return array;
    }
}
