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

package org.bouncycastle.asn1.pkcs;

import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Primitive;
import java.util.Enumeration;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.asn1.ASN1Encodable;
import java.io.IOException;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.ASN1BitString;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;

public class PrivateKeyInfo extends ASN1Object
{
    private ASN1Integer version;
    private AlgorithmIdentifier privateKeyAlgorithm;
    private ASN1OctetString privateKey;
    private ASN1Set attributes;
    private ASN1BitString publicKey;
    
    public static PrivateKeyInfo getInstance(final ASN1TaggedObject asn1TaggedObject, final boolean b) {
        return getInstance(ASN1Sequence.getInstance(asn1TaggedObject, b));
    }
    
    public static PrivateKeyInfo getInstance(final Object o) {
        if (o instanceof PrivateKeyInfo) {
            return (PrivateKeyInfo)o;
        }
        if (o != null) {
            return new PrivateKeyInfo(ASN1Sequence.getInstance(o));
        }
        return null;
    }
    
    private static int getVersionValue(final ASN1Integer asn1Integer) {
        final int intValueExact = asn1Integer.intValueExact();
        if (intValueExact < 0 || intValueExact > 1) {
            throw new IllegalArgumentException("invalid version for private key info");
        }
        return intValueExact;
    }
    
    public PrivateKeyInfo(final AlgorithmIdentifier algorithmIdentifier, final byte[] array) throws IOException {
        this(algorithmIdentifier, array, null, null);
    }
    
    public PrivateKeyInfo(final AlgorithmIdentifier algorithmIdentifier, final ASN1Encodable asn1Encodable) throws IOException {
        this(algorithmIdentifier, asn1Encodable, null, null);
    }
    
    public PrivateKeyInfo(final AlgorithmIdentifier algorithmIdentifier, final ASN1Encodable asn1Encodable, final ASN1Set set) throws IOException {
        this(algorithmIdentifier, asn1Encodable, set, null);
    }
    
    public PrivateKeyInfo(final AlgorithmIdentifier algorithmIdentifier, final byte[] array, final ASN1Set set) throws IOException {
        this(algorithmIdentifier, array, set, null);
    }
    
    public PrivateKeyInfo(final AlgorithmIdentifier algorithmIdentifier, final ASN1Encodable asn1Encodable, final ASN1Set set, final byte[] array) throws IOException {
        this(algorithmIdentifier, asn1Encodable.toASN1Primitive().getEncoded("DER"), set, array);
    }
    
    public PrivateKeyInfo(final AlgorithmIdentifier privateKeyAlgorithm, final byte[] array, final ASN1Set attributes, final byte[] array2) {
        this.version = new ASN1Integer((array2 != null) ? BigIntegers.ONE : BigIntegers.ZERO);
        this.privateKeyAlgorithm = privateKeyAlgorithm;
        this.privateKey = new DEROctetString(array);
        this.attributes = attributes;
        this.publicKey = ((array2 == null) ? null : new DERBitString(array2));
    }
    
    private PrivateKeyInfo(final ASN1Sequence asn1Sequence) {
        final Enumeration objects = asn1Sequence.getObjects();
        this.version = ASN1Integer.getInstance(objects.nextElement());
        final int versionValue = getVersionValue(this.version);
        this.privateKeyAlgorithm = AlgorithmIdentifier.getInstance(objects.nextElement());
        this.privateKey = ASN1OctetString.getInstance(objects.nextElement());
        int n = -1;
        while (objects.hasMoreElements()) {
            final ASN1TaggedObject asn1TaggedObject = objects.nextElement();
            final int tagNo = asn1TaggedObject.getTagNo();
            if (tagNo <= n) {
                throw new IllegalArgumentException("invalid optional field in private key info");
            }
            n = tagNo;
            switch (tagNo) {
                case 0: {
                    this.attributes = ASN1Set.getInstance(asn1TaggedObject, false);
                    continue;
                }
                case 1: {
                    if (versionValue < 1) {
                        throw new IllegalArgumentException("'publicKey' requires version v2(1) or later");
                    }
                    this.publicKey = ASN1BitString.getInstance(asn1TaggedObject, false);
                    continue;
                }
                default: {
                    throw new IllegalArgumentException("unknown optional field in private key info");
                }
            }
        }
    }
    
    public ASN1Integer getVersion() {
        return this.version;
    }
    
    public ASN1Set getAttributes() {
        return this.attributes;
    }
    
    public AlgorithmIdentifier getPrivateKeyAlgorithm() {
        return this.privateKeyAlgorithm;
    }
    
    public ASN1OctetString getPrivateKey() {
        return new DEROctetString(this.privateKey.getOctets());
    }
    
    public int getPrivateKeyLength() {
        return this.privateKey.getOctetsLength();
    }
    
    public ASN1Encodable parsePrivateKey() throws IOException {
        return ASN1Primitive.fromByteArray(this.privateKey.getOctets());
    }
    
    public boolean hasPublicKey() {
        return this.publicKey != null;
    }
    
    public ASN1Encodable parsePublicKey() throws IOException {
        return (this.publicKey == null) ? null : ASN1Primitive.fromByteArray(this.publicKey.getOctets());
    }
    
    public ASN1BitString getPublicKeyData() {
        return this.publicKey;
    }
    
    @Override
    public ASN1Primitive toASN1Primitive() {
        final ASN1EncodableVector asn1EncodableVector = new ASN1EncodableVector(5);
        asn1EncodableVector.add(this.version);
        asn1EncodableVector.add(this.privateKeyAlgorithm);
        asn1EncodableVector.add(this.privateKey);
        if (this.attributes != null) {
            asn1EncodableVector.add(new DERTaggedObject(false, 0, this.attributes));
        }
        if (this.publicKey != null) {
            asn1EncodableVector.add(new DERTaggedObject(false, 1, this.publicKey));
        }
        return new DERSequence(asn1EncodableVector);
    }
}
