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

package org.bouncycastle.pqc.crypto.sphincsplus;

import java.util.LinkedList;
import org.bouncycastle.util.Arrays;

class HT
{
    private final byte[] skSeed;
    private final byte[] pkSeed;
    SPHINCSPlusEngine engine;
    WotsPlus wots;
    final byte[] htPubKey;
    
    public HT(final SPHINCSPlusEngine engine, final byte[] skSeed, final byte[] pkSeed) {
        this.skSeed = skSeed;
        this.pkSeed = pkSeed;
        this.engine = engine;
        this.wots = new WotsPlus(engine);
        final ADRS adrs = new ADRS();
        adrs.setLayerAddress(engine.D - 1);
        adrs.setTreeAddress(0L);
        if (skSeed != null) {
            this.htPubKey = this.xmss_PKgen(skSeed, pkSeed, adrs);
        }
        else {
            this.htPubKey = null;
        }
    }
    
    byte[] sign(final byte[] array, long treeAddress, int n) {
        final ADRS adrs = new ADRS();
        adrs.setLayerAddress(0);
        adrs.setTreeAddress(treeAddress);
        final SIG_XMSS xmss_sign = this.xmss_sign(array, this.skSeed, n, this.pkSeed, adrs);
        final SIG_XMSS[] array2 = new SIG_XMSS[this.engine.D];
        array2[0] = xmss_sign;
        adrs.setLayerAddress(0);
        adrs.setTreeAddress(treeAddress);
        byte[] array3 = this.xmss_pkFromSig(n, xmss_sign, array, this.pkSeed, adrs);
        for (int i = 1; i < this.engine.D; ++i) {
            n = (int)(treeAddress & (long)((1 << this.engine.H_PRIME) - 1));
            treeAddress >>>= this.engine.H_PRIME;
            adrs.setLayerAddress(i);
            adrs.setTreeAddress(treeAddress);
            final SIG_XMSS xmss_sign2 = this.xmss_sign(array3, this.skSeed, n, this.pkSeed, adrs);
            array2[i] = xmss_sign2;
            if (i < this.engine.D - 1) {
                array3 = this.xmss_pkFromSig(n, xmss_sign2, array3, this.pkSeed, adrs);
            }
        }
        final byte[][] array4 = new byte[array2.length][];
        for (int j = 0; j != array4.length; ++j) {
            array4[j] = Arrays.concatenate(array2[j].sig, Arrays.concatenate(array2[j].auth));
        }
        return Arrays.concatenate(array4);
    }
    
    byte[] xmss_PKgen(final byte[] array, final byte[] array2, final ADRS adrs) {
        return this.treehash(array, 0, this.engine.H_PRIME, array2, adrs);
    }
    
    byte[] xmss_pkFromSig(final int n, final SIG_XMSS sig_XMSS, final byte[] array, final byte[] array2, final ADRS adrs) {
        final ADRS adrs2 = new ADRS(adrs);
        adrs2.setTypeAndClear(0);
        adrs2.setKeyPairAddress(n);
        final byte[] wotsSig = sig_XMSS.getWOTSSig();
        final byte[][] xmssauth = sig_XMSS.getXMSSAUTH();
        byte[] pkFromSig = this.wots.pkFromSig(wotsSig, array, array2, adrs2);
        adrs2.setTypeAndClear(2);
        adrs2.setTreeIndex(n);
        for (int i = 0; i < this.engine.H_PRIME; ++i) {
            adrs2.setTreeHeight(i + 1);
            byte[] array3;
            if (n / (1 << i) % 2 == 0) {
                adrs2.setTreeIndex(adrs2.getTreeIndex() / 2);
                array3 = this.engine.H(array2, adrs2, pkFromSig, xmssauth[i]);
            }
            else {
                adrs2.setTreeIndex((adrs2.getTreeIndex() - 1) / 2);
                array3 = this.engine.H(array2, adrs2, xmssauth[i], pkFromSig);
            }
            pkFromSig = array3;
        }
        return pkFromSig;
    }
    
    SIG_XMSS xmss_sign(final byte[] array, final byte[] array2, final int keyPairAddress, final byte[] array3, final ADRS adrs) {
        final byte[][] array4 = new byte[this.engine.H_PRIME][];
        final ADRS adrs2 = new ADRS(adrs);
        adrs2.setTypeAndClear(2);
        adrs2.setLayerAddress(adrs.getLayerAddress());
        adrs2.setTreeAddress(adrs.getTreeAddress());
        for (int i = 0; i < this.engine.H_PRIME; ++i) {
            array4[i] = this.treehash(array2, (keyPairAddress >>> i ^ 0x1) << i, i, array3, adrs2);
        }
        final ADRS adrs3 = new ADRS(adrs);
        adrs3.setTypeAndClear(0);
        adrs3.setKeyPairAddress(keyPairAddress);
        return new SIG_XMSS(this.wots.sign(array, array2, array3, adrs3), array4);
    }
    
    byte[] treehash(final byte[] array, final int n, final int n2, final byte[] array2, final ADRS adrs) {
        if (n >>> n2 << n2 != n) {
            return null;
        }
        final LinkedList list = new LinkedList();
        final ADRS adrs2 = new ADRS(adrs);
        for (int i = 0; i < 1 << n2; ++i) {
            adrs2.setTypeAndClear(0);
            adrs2.setKeyPairAddress(n + i);
            byte[] array3 = this.wots.pkGen(array, array2, adrs2);
            adrs2.setTypeAndClear(2);
            adrs2.setTreeHeight(1);
            adrs2.setTreeIndex(n + i);
            int n3 = 1;
            int treeIndex = n + i;
            while (!list.isEmpty() && list.get(0).nodeHeight == n3) {
                treeIndex = (treeIndex - 1) / 2;
                adrs2.setTreeIndex(treeIndex);
                array3 = this.engine.H(array2, adrs2, list.remove(0).nodeValue, array3);
                adrs2.setTreeHeight(++n3);
            }
            list.add(0, new NodeEntry(array3, n3));
        }
        return ((NodeEntry)list.get(0)).nodeValue;
    }
    
    public boolean verify(final byte[] array, final SIG_XMSS[] array2, final byte[] array3, long n, int n2, final byte[] array4) {
        final ADRS adrs = new ADRS();
        final SIG_XMSS sig_XMSS = array2[0];
        adrs.setLayerAddress(0);
        adrs.setTreeAddress(n);
        byte[] array5 = this.xmss_pkFromSig(n2, sig_XMSS, array, array3, adrs);
        for (int i = 1; i < this.engine.D; ++i) {
            n2 = (int)(n & (long)((1 << this.engine.H_PRIME) - 1));
            n >>>= this.engine.H_PRIME;
            final SIG_XMSS sig_XMSS2 = array2[i];
            adrs.setLayerAddress(i);
            adrs.setTreeAddress(n);
            array5 = this.xmss_pkFromSig(n2, sig_XMSS2, array5, array3, adrs);
        }
        return Arrays.areEqual(array4, array5);
    }
}
