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

package org.bouncycastle.pqc.crypto.lms;

import java.util.List;
import org.bouncycastle.pqc.crypto.ExhaustedPrivateKeyException;
import java.util.Arrays;

class HSS
{
    public static HSSPrivateKeyParameters generateHSSKeyPair(final HSSKeyGenerationParameters hssKeyGenerationParameters) {
        final LMSPrivateKeyParameters[] a = new LMSPrivateKeyParameters[hssKeyGenerationParameters.getDepth()];
        final LMSSignature[] a2 = new LMSSignature[hssKeyGenerationParameters.getDepth() - 1];
        final byte[] bytes = new byte[hssKeyGenerationParameters.getLmsParameters()[0].getLMSigParam().getM()];
        hssKeyGenerationParameters.getRandom().nextBytes(bytes);
        final byte[] bytes2 = new byte[16];
        hssKeyGenerationParameters.getRandom().nextBytes(bytes2);
        final byte[] array = new byte[0];
        long n = 1L;
        for (int i = 0; i < a.length; ++i) {
            if (i == 0) {
                a[i] = new LMSPrivateKeyParameters(hssKeyGenerationParameters.getLmsParameters()[i].getLMSigParam(), hssKeyGenerationParameters.getLmsParameters()[i].getLMOTSParam(), 0, bytes2, 1 << hssKeyGenerationParameters.getLmsParameters()[i].getLMSigParam().getH(), bytes);
            }
            else {
                a[i] = new PlaceholderLMSPrivateKey(hssKeyGenerationParameters.getLmsParameters()[i].getLMSigParam(), hssKeyGenerationParameters.getLmsParameters()[i].getLMOTSParam(), -1, array, 1 << hssKeyGenerationParameters.getLmsParameters()[i].getLMSigParam().getH(), array);
            }
            n *= 1 << hssKeyGenerationParameters.getLmsParameters()[i].getLMSigParam().getH();
        }
        if (n == 0L) {
            n = Long.MAX_VALUE;
        }
        return new HSSPrivateKeyParameters(hssKeyGenerationParameters.getDepth(), Arrays.asList(a), Arrays.asList(a2), 0L, n);
    }
    
    public static void incrementIndex(final HSSPrivateKeyParameters hssPrivateKeyParameters) {
        synchronized (hssPrivateKeyParameters) {
            rangeTestKeys(hssPrivateKeyParameters);
            hssPrivateKeyParameters.incIndex();
            hssPrivateKeyParameters.getKeys().get(hssPrivateKeyParameters.getL() - 1).incIndex();
        }
    }
    
    static void rangeTestKeys(final HSSPrivateKeyParameters hssPrivateKeyParameters) {
        synchronized (hssPrivateKeyParameters) {
            if (hssPrivateKeyParameters.getIndex() >= hssPrivateKeyParameters.getIndexLimit()) {
                throw new ExhaustedPrivateKeyException("hss private key" + (hssPrivateKeyParameters.isShard() ? " shard" : "") + " is exhausted");
            }
            int i;
            final int n = i = hssPrivateKeyParameters.getL();
            final List<LMSPrivateKeyParameters> keys = hssPrivateKeyParameters.getKeys();
            while (keys.get(i - 1).getIndex() == 1 << keys.get(i - 1).getSigParameters().getH()) {
                --i;
                if (i == 0) {
                    throw new ExhaustedPrivateKeyException("hss private key" + (hssPrivateKeyParameters.isShard() ? " shard" : "") + " is exhausted the maximum limit for this HSS private key");
                }
            }
            while (i < n) {
                hssPrivateKeyParameters.replaceConsumedKey(i);
                ++i;
            }
        }
    }
    
    public static HSSSignature generateSignature(final HSSPrivateKeyParameters hssPrivateKeyParameters, final byte[] array) {
        final int l = hssPrivateKeyParameters.getL();
        final LMSPrivateKeyParameters lmsPrivateKeyParameters;
        final LMSSignedPubKey[] array2;
        synchronized (hssPrivateKeyParameters) {
            rangeTestKeys(hssPrivateKeyParameters);
            final List<LMSPrivateKeyParameters> keys = hssPrivateKeyParameters.getKeys();
            final List<LMSSignature> sig = hssPrivateKeyParameters.getSig();
            lmsPrivateKeyParameters = hssPrivateKeyParameters.getKeys().get(l - 1);
            int i = 0;
            array2 = new LMSSignedPubKey[l - 1];
            while (i < l - 1) {
                array2[i] = new LMSSignedPubKey(sig.get(i), keys.get(i + 1).getPublicKey());
                ++i;
            }
            hssPrivateKeyParameters.incIndex();
        }
        final LMSContext withSignedPublicKeys = lmsPrivateKeyParameters.generateLMSContext().withSignedPublicKeys(array2);
        withSignedPublicKeys.update(array, 0, array.length);
        return generateSignature(l, withSignedPublicKeys);
    }
    
    public static HSSSignature generateSignature(final int n, final LMSContext lmsContext) {
        return new HSSSignature(n - 1, lmsContext.getSignedPubKeys(), LMS.generateSign(lmsContext));
    }
    
    public static boolean verifySignature(final HSSPublicKeyParameters hssPublicKeyParameters, final HSSSignature hssSignature, final byte[] array) {
        final int getlMinus1 = hssSignature.getlMinus1();
        if (getlMinus1 + 1 != hssPublicKeyParameters.getL()) {
            return false;
        }
        final LMSSignature[] array2 = new LMSSignature[getlMinus1 + 1];
        final LMSPublicKeyParameters[] array3 = new LMSPublicKeyParameters[getlMinus1];
        for (int i = 0; i < getlMinus1; ++i) {
            array2[i] = hssSignature.getSignedPubKey()[i].getSignature();
            array3[i] = hssSignature.getSignedPubKey()[i].getPublicKey();
        }
        array2[getlMinus1] = hssSignature.getSignature();
        LMSPublicKeyParameters lmsPublicKey = hssPublicKeyParameters.getLMSPublicKey();
        for (int j = 0; j < getlMinus1; ++j) {
            if (!LMS.verifySignature(lmsPublicKey, array2[j], array3[j].toByteArray())) {
                return false;
            }
            try {
                lmsPublicKey = array3[j];
            }
            catch (final Exception cause) {
                throw new IllegalStateException(cause.getMessage(), cause);
            }
        }
        return LMS.verifySignature(lmsPublicKey, array2[getlMinus1], array);
    }
    
    static class PlaceholderLMSPrivateKey extends LMSPrivateKeyParameters
    {
        public PlaceholderLMSPrivateKey(final LMSigParameters lmSigParameters, final LMOtsParameters lmOtsParameters, final int n, final byte[] array, final int n2, final byte[] array2) {
            super(lmSigParameters, lmOtsParameters, n, array, n2, array2);
        }
        
        @Override
        LMOtsPrivateKey getNextOtsPrivateKey() {
            throw new RuntimeException("placeholder only");
        }
        
        @Override
        public LMSPublicKeyParameters getPublicKey() {
            throw new RuntimeException("placeholder only");
        }
    }
}
