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

package org.bouncycastle.pqc.crypto.lms;

import java.util.Iterator;
import org.bouncycastle.util.Encodable;
import java.util.Collection;
import java.util.Arrays;
import org.bouncycastle.util.io.Streams;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

public class HSSPrivateKeyParameters extends LMSKeyParameters implements LMSContextBasedSigner
{
    private final int l;
    private final boolean isShard;
    private List<LMSPrivateKeyParameters> keys;
    private List<LMSSignature> sig;
    private final long indexLimit;
    private long index;
    private HSSPublicKeyParameters publicKey;
    
    public HSSPrivateKeyParameters(final LMSPrivateKeyParameters o, final long index, final long indexLimit) {
        super(true);
        this.index = 0L;
        this.l = 1;
        this.keys = Collections.singletonList(o);
        this.sig = Collections.emptyList();
        this.index = index;
        this.indexLimit = indexLimit;
        this.isShard = false;
        this.resetKeyToIndex();
    }
    
    public HSSPrivateKeyParameters(final int l, final List<LMSPrivateKeyParameters> list, final List<LMSSignature> list2, final long index, final long indexLimit) {
        super(true);
        this.index = 0L;
        this.l = l;
        this.keys = Collections.unmodifiableList((List<? extends LMSPrivateKeyParameters>)list);
        this.sig = Collections.unmodifiableList((List<? extends LMSSignature>)list2);
        this.index = index;
        this.indexLimit = indexLimit;
        this.isShard = false;
        this.resetKeyToIndex();
    }
    
    private HSSPrivateKeyParameters(final int l, final List<LMSPrivateKeyParameters> list, final List<LMSSignature> list2, final long index, final long indexLimit, final boolean isShard) {
        super(true);
        this.index = 0L;
        this.l = l;
        this.keys = Collections.unmodifiableList((List<? extends LMSPrivateKeyParameters>)list);
        this.sig = Collections.unmodifiableList((List<? extends LMSSignature>)list2);
        this.index = index;
        this.indexLimit = indexLimit;
        this.isShard = isShard;
    }
    
    public static HSSPrivateKeyParameters getInstance(final byte[] array, final byte[] array2) throws IOException {
        final HSSPrivateKeyParameters instance = getInstance(array);
        instance.publicKey = HSSPublicKeyParameters.getInstance(array2);
        return instance;
    }
    
    public static HSSPrivateKeyParameters getInstance(final Object obj) throws IOException {
        if (obj instanceof HSSPrivateKeyParameters) {
            return (HSSPrivateKeyParameters)obj;
        }
        if (obj instanceof DataInputStream) {
            if (((DataInputStream)obj).readInt() != 0) {
                throw new IllegalStateException("unknown version for hss private key");
            }
            final int int1 = ((DataInputStream)obj).readInt();
            final long long1 = ((DataInputStream)obj).readLong();
            final long long2 = ((DataInputStream)obj).readLong();
            final boolean boolean1 = ((DataInputStream)obj).readBoolean();
            final ArrayList list = new ArrayList();
            final ArrayList list2 = new ArrayList();
            for (int i = 0; i < int1; ++i) {
                list.add(LMSPrivateKeyParameters.getInstance(obj));
            }
            for (int j = 0; j < int1 - 1; ++j) {
                list2.add(LMSSignature.getInstance(obj));
            }
            return new HSSPrivateKeyParameters(int1, list, list2, long1, long2, boolean1);
        }
        else {
            if (obj instanceof byte[]) {
                InputStream inputStream = null;
                try {
                    inputStream = new DataInputStream(new ByteArrayInputStream((byte[])obj));
                    try {
                        return getInstance(inputStream);
                    }
                    catch (final Exception ex) {
                        final LMSPrivateKeyParameters instance = LMSPrivateKeyParameters.getInstance(obj);
                        return new HSSPrivateKeyParameters(instance, instance.getIndex(), instance.getIndexLimit());
                    }
                }
                finally {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                }
            }
            if (obj instanceof InputStream) {
                return getInstance(Streams.readAll((InputStream)obj));
            }
            throw new IllegalArgumentException("cannot parse " + obj);
        }
    }
    
    public int getL() {
        return this.l;
    }
    
    public synchronized long getIndex() {
        return this.index;
    }
    
    public synchronized LMSParameters[] getLMSParameters() {
        final int size = this.keys.size();
        final LMSParameters[] array = new LMSParameters[size];
        for (int i = 0; i < size; ++i) {
            final LMSPrivateKeyParameters lmsPrivateKeyParameters = this.keys.get(i);
            array[i] = new LMSParameters(lmsPrivateKeyParameters.getSigParameters(), lmsPrivateKeyParameters.getOtsParameters());
        }
        return array;
    }
    
    synchronized void incIndex() {
        ++this.index;
    }
    
    private static HSSPrivateKeyParameters makeCopy(final HSSPrivateKeyParameters hssPrivateKeyParameters) {
        try {
            return getInstance(hssPrivateKeyParameters.getEncoded());
        }
        catch (final Exception cause) {
            throw new RuntimeException(cause.getMessage(), cause);
        }
    }
    
    protected void updateHierarchy(final LMSPrivateKeyParameters[] a, final LMSSignature[] a2) {
        synchronized (this) {
            this.keys = Collections.unmodifiableList((List<? extends LMSPrivateKeyParameters>)Arrays.asList((T[])a));
            this.sig = Collections.unmodifiableList((List<? extends LMSSignature>)Arrays.asList((T[])a2));
        }
    }
    
    boolean isShard() {
        return this.isShard;
    }
    
    long getIndexLimit() {
        return this.indexLimit;
    }
    
    @Override
    public long getUsagesRemaining() {
        return this.getIndexLimit() - this.getIndex();
    }
    
    LMSPrivateKeyParameters getRootKey() {
        return this.keys.get(0);
    }
    
    public HSSPrivateKeyParameters extractKeyShard(final int n) {
        synchronized (this) {
            if (n < 0) {
                throw new IllegalArgumentException("usageCount cannot be negative");
            }
            if (n > this.indexLimit - this.index) {
                throw new IllegalArgumentException("usageCount exceeds usages remaining in current leaf");
            }
            final long index = this.index;
            final long index2 = this.index + n;
            this.index = index2;
            final HSSPrivateKeyParameters copy = makeCopy(new HSSPrivateKeyParameters(this.l, new ArrayList<LMSPrivateKeyParameters>(this.getKeys()), new ArrayList<LMSSignature>(this.getSig()), index, index2, true));
            this.resetKeyToIndex();
            return copy;
        }
    }
    
    synchronized List<LMSPrivateKeyParameters> getKeys() {
        return this.keys;
    }
    
    synchronized List<LMSSignature> getSig() {
        return this.sig;
    }
    
    void resetKeyToIndex() {
        final List<LMSPrivateKeyParameters> keys = this.getKeys();
        final long[] array = new long[keys.size()];
        long index = this.getIndex();
        for (int i = keys.size() - 1; i >= 0; --i) {
            final LMSigParameters sigParameters = keys.get(i).getSigParameters();
            array[i] = (index & (long)((1 << sigParameters.getH()) - 1));
            index >>>= sigParameters.getH();
        }
        boolean b = false;
        final LMSPrivateKeyParameters[] array2 = keys.toArray(new LMSPrivateKeyParameters[keys.size()]);
        final LMSSignature[] array3 = this.sig.toArray(new LMSSignature[this.sig.size()]);
        final LMSPrivateKeyParameters rootKey = this.getRootKey();
        if (array2[0].getIndex() - 1 != array[0]) {
            array2[0] = LMS.generateKeys(rootKey.getSigParameters(), rootKey.getOtsParameters(), (int)array[0], rootKey.getI(), rootKey.getMasterSecret());
            b = true;
        }
        for (int j = 1; j < array.length; ++j) {
            final LMSPrivateKeyParameters lmsPrivateKeyParameters = array2[j - 1];
            final int n = lmsPrivateKeyParameters.getOtsParameters().getN();
            final byte[] array4 = new byte[16];
            final byte[] array5 = new byte[n];
            final SeedDerive seedDerive = new SeedDerive(lmsPrivateKeyParameters.getI(), lmsPrivateKeyParameters.getMasterSecret(), DigestUtil.getDigest(lmsPrivateKeyParameters.getOtsParameters()));
            seedDerive.setQ((int)array[j - 1]);
            seedDerive.setJ(-2);
            seedDerive.deriveSeed(array5, true);
            final byte[] array6 = new byte[n];
            seedDerive.deriveSeed(array6, false);
            System.arraycopy(array6, 0, array4, 0, array4.length);
            final boolean b2 = (j < array.length - 1) ? (array[j] == array2[j].getIndex() - 1) : (array[j] == array2[j].getIndex());
            if (!org.bouncycastle.util.Arrays.areEqual(array4, array2[j].getI()) || !org.bouncycastle.util.Arrays.areEqual(array5, array2[j].getMasterSecret())) {
                array2[j] = LMS.generateKeys(keys.get(j).getSigParameters(), keys.get(j).getOtsParameters(), (int)array[j], array4, array5);
                array3[j - 1] = LMS.generateSign(array2[j - 1], array2[j].getPublicKey().toByteArray());
                b = true;
            }
            else if (!b2) {
                array2[j] = LMS.generateKeys(keys.get(j).getSigParameters(), keys.get(j).getOtsParameters(), (int)array[j], array4, array5);
                b = true;
            }
        }
        if (b) {
            this.updateHierarchy(array2, array3);
        }
    }
    
    public synchronized HSSPublicKeyParameters getPublicKey() {
        return new HSSPublicKeyParameters(this.l, this.getRootKey().getPublicKey());
    }
    
    void replaceConsumedKey(final int n) {
        final LMOtsPrivateKey currentOTSKey = this.keys.get(n - 1).getCurrentOTSKey();
        final int n2 = currentOTSKey.getParameter().getN();
        final SeedDerive derivationFunction = currentOTSKey.getDerivationFunction();
        derivationFunction.setJ(-2);
        final byte[] array = new byte[n2];
        derivationFunction.deriveSeed(array, true);
        final byte[] array2 = new byte[n2];
        derivationFunction.deriveSeed(array2, false);
        final byte[] array3 = new byte[16];
        System.arraycopy(array2, 0, array3, 0, array3.length);
        final ArrayList list = new ArrayList((Collection<? extends E>)this.keys);
        final LMSPrivateKeyParameters lmsPrivateKeyParameters = this.keys.get(n);
        list.set(n, LMS.generateKeys(lmsPrivateKeyParameters.getSigParameters(), lmsPrivateKeyParameters.getOtsParameters(), 0, array3, array));
        final ArrayList list2 = new ArrayList((Collection<? extends E>)this.sig);
        list2.set(n - 1, LMS.generateSign((LMSPrivateKeyParameters)list.get(n - 1), ((LMSPrivateKeyParameters)list.get(n)).getPublicKey().toByteArray()));
        this.keys = (List<LMSPrivateKeyParameters>)Collections.unmodifiableList((List<?>)list);
        this.sig = (List<LMSSignature>)Collections.unmodifiableList((List<?>)list2);
    }
    
    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || this.getClass() != o.getClass()) {
            return false;
        }
        final HSSPrivateKeyParameters hssPrivateKeyParameters = (HSSPrivateKeyParameters)o;
        return this.l == hssPrivateKeyParameters.l && this.isShard == hssPrivateKeyParameters.isShard && this.indexLimit == hssPrivateKeyParameters.indexLimit && this.index == hssPrivateKeyParameters.index && this.keys.equals(hssPrivateKeyParameters.keys) && this.sig.equals(hssPrivateKeyParameters.sig);
    }
    
    @Override
    public synchronized byte[] getEncoded() throws IOException {
        final Composer bool = Composer.compose().u32str(0).u32str(this.l).u64str(this.index).u64str(this.indexLimit).bool(this.isShard);
        final Iterator<LMSPrivateKeyParameters> iterator = this.keys.iterator();
        while (iterator.hasNext()) {
            bool.bytes(iterator.next());
        }
        final Iterator<LMSSignature> iterator2 = this.sig.iterator();
        while (iterator2.hasNext()) {
            bool.bytes(iterator2.next());
        }
        return bool.build();
    }
    
    @Override
    public int hashCode() {
        return 31 * (31 * (31 * (31 * (31 * this.l + (this.isShard ? 1 : 0)) + this.keys.hashCode()) + this.sig.hashCode()) + (int)(this.indexLimit ^ this.indexLimit >>> 32)) + (int)(this.index ^ this.index >>> 32);
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return makeCopy(this);
    }
    
    @Override
    public LMSContext generateLMSContext() {
        final int l = this.getL();
        final LMSPrivateKeyParameters lmsPrivateKeyParameters;
        final LMSSignedPubKey[] array;
        synchronized (this) {
            HSS.rangeTestKeys(this);
            final List<LMSPrivateKeyParameters> keys = this.getKeys();
            final List<LMSSignature> sig = this.getSig();
            lmsPrivateKeyParameters = this.getKeys().get(l - 1);
            int i = 0;
            array = new LMSSignedPubKey[l - 1];
            while (i < l - 1) {
                array[i] = new LMSSignedPubKey(sig.get(i), keys.get(i + 1).getPublicKey());
                ++i;
            }
            this.incIndex();
        }
        return lmsPrivateKeyParameters.generateLMSContext().withSignedPublicKeys(array);
    }
    
    @Override
    public byte[] generateSignature(final LMSContext lmsContext) {
        try {
            return HSS.generateSignature(this.getL(), lmsContext).getEncoded();
        }
        catch (final IOException cause) {
            throw new IllegalStateException("unable to encode signature: " + cause.getMessage(), cause);
        }
    }
}
