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

package org.bouncycastle.pqc.jcajce.provider.xmss;

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.pqc.crypto.util.PrivateKeyInfoFactory;
import org.bouncycastle.pqc.crypto.util.PrivateKeyFactory;
import org.bouncycastle.pqc.asn1.XMSSKeyParams;
import java.io.IOException;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.pqc.crypto.xmss.XMSSPrivateKeyParameters;
import org.bouncycastle.pqc.jcajce.interfaces.XMSSPrivateKey;
import java.security.PrivateKey;

public class BCXMSSPrivateKey implements PrivateKey, XMSSPrivateKey
{
    private static final long serialVersionUID = 8568701712864512338L;
    private transient XMSSPrivateKeyParameters keyParams;
    private transient ASN1ObjectIdentifier treeDigest;
    private transient ASN1Set attributes;
    
    public BCXMSSPrivateKey(final ASN1ObjectIdentifier treeDigest, final XMSSPrivateKeyParameters keyParams) {
        this.treeDigest = treeDigest;
        this.keyParams = keyParams;
    }
    
    public BCXMSSPrivateKey(final PrivateKeyInfo privateKeyInfo) throws IOException {
        this.init(privateKeyInfo);
    }
    
    private void init(final PrivateKeyInfo privateKeyInfo) throws IOException {
        this.attributes = privateKeyInfo.getAttributes();
        this.treeDigest = XMSSKeyParams.getInstance(privateKeyInfo.getPrivateKeyAlgorithm().getParameters()).getTreeDigest().getAlgorithm();
        this.keyParams = (XMSSPrivateKeyParameters)PrivateKeyFactory.createKey(privateKeyInfo);
    }
    
    @Override
    public long getIndex() {
        if (this.getUsagesRemaining() == 0L) {
            throw new IllegalStateException("key exhausted");
        }
        return this.keyParams.getIndex();
    }
    
    @Override
    public long getUsagesRemaining() {
        return this.keyParams.getUsagesRemaining();
    }
    
    @Override
    public XMSSPrivateKey extractKeyShard(final int n) {
        return new BCXMSSPrivateKey(this.treeDigest, this.keyParams.extractKeyShard(n));
    }
    
    @Override
    public String getAlgorithm() {
        return "XMSS";
    }
    
    @Override
    public String getFormat() {
        return "PKCS#8";
    }
    
    @Override
    public byte[] getEncoded() {
        try {
            return PrivateKeyInfoFactory.createPrivateKeyInfo(this.keyParams, this.attributes).getEncoded();
        }
        catch (final IOException ex) {
            return null;
        }
    }
    
    @Override
    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        }
        if (o instanceof BCXMSSPrivateKey) {
            final BCXMSSPrivateKey bcxmssPrivateKey = (BCXMSSPrivateKey)o;
            return this.treeDigest.equals(bcxmssPrivateKey.treeDigest) && Arrays.areEqual(this.keyParams.toByteArray(), bcxmssPrivateKey.keyParams.toByteArray());
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        return this.treeDigest.hashCode() + 37 * Arrays.hashCode(this.keyParams.toByteArray());
    }
    
    CipherParameters getKeyParams() {
        return this.keyParams;
    }
    
    ASN1ObjectIdentifier getTreeDigestOID() {
        return this.treeDigest;
    }
    
    @Override
    public int getHeight() {
        return this.keyParams.getParameters().getHeight();
    }
    
    @Override
    public String getTreeDigest() {
        return DigestUtil.getXMSSDigestName(this.treeDigest);
    }
    
    private void readObject(final ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
        objectInputStream.defaultReadObject();
        this.init(PrivateKeyInfo.getInstance(objectInputStream.readObject()));
    }
    
    private void writeObject(final ObjectOutputStream objectOutputStream) throws IOException {
        objectOutputStream.defaultWriteObject();
        objectOutputStream.writeObject(this.getEncoded());
    }
}
