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

package org.bouncycastle.crypto.util;

import java.math.BigInteger;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.util.Strings;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.sec.ECPrivateKey;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.asn1.ASN1Sequence;
import java.io.IOException;
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;

public class OpenSSHPrivateKeyUtil
{
    static final byte[] AUTH_MAGIC;
    
    private OpenSSHPrivateKeyUtil() {
    }
    
    public static byte[] encodePrivateKey(final AsymmetricKeyParameter asymmetricKeyParameter) throws IOException {
        if (asymmetricKeyParameter == null) {
            throw new IllegalArgumentException("param is null");
        }
        if (asymmetricKeyParameter instanceof RSAPrivateCrtKeyParameters) {
            return PrivateKeyInfoFactory.createPrivateKeyInfo(asymmetricKeyParameter).parsePrivateKey().toASN1Primitive().getEncoded();
        }
        if (asymmetricKeyParameter instanceof ECPrivateKeyParameters) {
            return PrivateKeyInfoFactory.createPrivateKeyInfo(asymmetricKeyParameter).parsePrivateKey().toASN1Primitive().getEncoded();
        }
        if (asymmetricKeyParameter instanceof DSAPrivateKeyParameters) {
            final DSAPrivateKeyParameters dsaPrivateKeyParameters = (DSAPrivateKeyParameters)asymmetricKeyParameter;
            final DSAParameters parameters = dsaPrivateKeyParameters.getParameters();
            final ASN1EncodableVector asn1EncodableVector = new ASN1EncodableVector();
            asn1EncodableVector.add(new ASN1Integer(0L));
            asn1EncodableVector.add(new ASN1Integer(parameters.getP()));
            asn1EncodableVector.add(new ASN1Integer(parameters.getQ()));
            asn1EncodableVector.add(new ASN1Integer(parameters.getG()));
            asn1EncodableVector.add(new ASN1Integer(parameters.getG().modPow(dsaPrivateKeyParameters.getX(), parameters.getP())));
            asn1EncodableVector.add(new ASN1Integer(dsaPrivateKeyParameters.getX()));
            try {
                return new DERSequence(asn1EncodableVector).getEncoded();
            }
            catch (final Exception ex) {
                throw new IllegalStateException("unable to encode DSAPrivateKeyParameters " + ex.getMessage());
            }
        }
        if (asymmetricKeyParameter instanceof Ed25519PrivateKeyParameters) {
            final Ed25519PublicKeyParameters generatePublicKey = ((Ed25519PrivateKeyParameters)asymmetricKeyParameter).generatePublicKey();
            final SSHBuilder sshBuilder = new SSHBuilder();
            sshBuilder.writeBytes(OpenSSHPrivateKeyUtil.AUTH_MAGIC);
            sshBuilder.writeString("none");
            sshBuilder.writeString("none");
            sshBuilder.writeString("");
            sshBuilder.u32(1);
            sshBuilder.writeBlock(OpenSSHPublicKeyUtil.encodePublicKey(generatePublicKey));
            final SSHBuilder sshBuilder2 = new SSHBuilder();
            final int nextInt = CryptoServicesRegistrar.getSecureRandom().nextInt();
            sshBuilder2.u32(nextInt);
            sshBuilder2.u32(nextInt);
            sshBuilder2.writeString("ssh-ed25519");
            final byte[] encoded = generatePublicKey.getEncoded();
            sshBuilder2.writeBlock(encoded);
            sshBuilder2.writeBlock(Arrays.concatenate(((Ed25519PrivateKeyParameters)asymmetricKeyParameter).getEncoded(), encoded));
            sshBuilder2.writeString("");
            sshBuilder.writeBlock(sshBuilder2.getPaddedBytes());
            return sshBuilder.getBytes();
        }
        throw new IllegalArgumentException("unable to convert " + asymmetricKeyParameter.getClass().getName() + " to openssh private key");
    }
    
    public static AsymmetricKeyParameter parsePrivateKeyBlob(final byte[] array) {
        AsymmetricKeyParameter asymmetricKeyParameter = null;
        if (array[0] == 48) {
            final ASN1Sequence instance = ASN1Sequence.getInstance(array);
            if (instance.size() == 6) {
                if (allIntegers(instance) && ((ASN1Integer)instance.getObjectAt(0)).getPositiveValue().equals(BigIntegers.ZERO)) {
                    asymmetricKeyParameter = new DSAPrivateKeyParameters(((ASN1Integer)instance.getObjectAt(5)).getPositiveValue(), new DSAParameters(((ASN1Integer)instance.getObjectAt(1)).getPositiveValue(), ((ASN1Integer)instance.getObjectAt(2)).getPositiveValue(), ((ASN1Integer)instance.getObjectAt(3)).getPositiveValue()));
                }
            }
            else if (instance.size() == 9) {
                if (allIntegers(instance) && ((ASN1Integer)instance.getObjectAt(0)).getPositiveValue().equals(BigIntegers.ZERO)) {
                    final RSAPrivateKey instance2 = RSAPrivateKey.getInstance(instance);
                    asymmetricKeyParameter = new RSAPrivateCrtKeyParameters(instance2.getModulus(), instance2.getPublicExponent(), instance2.getPrivateExponent(), instance2.getPrime1(), instance2.getPrime2(), instance2.getExponent1(), instance2.getExponent2(), instance2.getCoefficient());
                }
            }
            else if (instance.size() == 4 && instance.getObjectAt(3) instanceof ASN1TaggedObject && instance.getObjectAt(2) instanceof ASN1TaggedObject) {
                final ECPrivateKey instance3 = ECPrivateKey.getInstance(instance);
                final X962Parameters instance4 = X962Parameters.getInstance(instance3.getParametersObject().toASN1Primitive());
                ECDomainParameters lookup;
                if (instance4.isNamedCurve()) {
                    lookup = ECNamedDomainParameters.lookup(ASN1ObjectIdentifier.getInstance(instance4.getParameters()));
                }
                else {
                    lookup = new ECDomainParameters(X9ECParameters.getInstance(instance4.getParameters()));
                }
                asymmetricKeyParameter = new ECPrivateKeyParameters(instance3.getKey(), lookup);
            }
        }
        else {
            final SSHBuffer sshBuffer = new SSHBuffer(OpenSSHPrivateKeyUtil.AUTH_MAGIC, array);
            if (!"none".equals(sshBuffer.readString())) {
                throw new IllegalStateException("encrypted keys not supported");
            }
            sshBuffer.skipBlock();
            sshBuffer.skipBlock();
            if (sshBuffer.readU32() != 1) {
                throw new IllegalStateException("multiple keys not supported");
            }
            OpenSSHPublicKeyUtil.parsePublicKey(sshBuffer.readBlock());
            final byte[] paddedBlock = sshBuffer.readPaddedBlock();
            if (sshBuffer.hasRemaining()) {
                throw new IllegalArgumentException("decoded key has trailing data");
            }
            final SSHBuffer sshBuffer2 = new SSHBuffer(paddedBlock);
            if (sshBuffer2.readU32() != sshBuffer2.readU32()) {
                throw new IllegalStateException("private key check values are not the same");
            }
            final String string = sshBuffer2.readString();
            if ("ssh-ed25519".equals(string)) {
                sshBuffer2.readBlock();
                final byte[] block = sshBuffer2.readBlock();
                if (block.length != 64) {
                    throw new IllegalStateException("private key value of wrong length");
                }
                asymmetricKeyParameter = new Ed25519PrivateKeyParameters(block, 0);
            }
            else if (string.startsWith("ecdsa")) {
                final ASN1ObjectIdentifier byName = SSHNamedCurves.getByName(Strings.fromByteArray(sshBuffer2.readBlock()));
                if (byName == null) {
                    throw new IllegalStateException("OID not found for: " + string);
                }
                final X9ECParameters byOID = NISTNamedCurves.getByOID(byName);
                if (byOID == null) {
                    throw new IllegalStateException("Curve not found for: " + byName);
                }
                sshBuffer2.readBlock();
                asymmetricKeyParameter = new ECPrivateKeyParameters(new BigInteger(1, sshBuffer2.readBlock()), new ECNamedDomainParameters(byName, byOID));
            }
            else if (string.startsWith("ssh-rsa")) {
                final BigInteger bigInteger = new BigInteger(1, sshBuffer2.readBlock());
                final BigInteger bigInteger2 = new BigInteger(1, sshBuffer2.readBlock());
                final BigInteger bigInteger3 = new BigInteger(1, sshBuffer2.readBlock());
                final BigInteger bigInteger4 = new BigInteger(1, sshBuffer2.readBlock());
                final BigInteger bigInteger5 = new BigInteger(1, sshBuffer2.readBlock());
                final BigInteger bigInteger6 = new BigInteger(1, sshBuffer2.readBlock());
                asymmetricKeyParameter = new RSAPrivateCrtKeyParameters(bigInteger, bigInteger2, bigInteger3, bigInteger5, bigInteger6, bigInteger3.remainder(bigInteger5.subtract(BigIntegers.ONE)), bigInteger3.remainder(bigInteger6.subtract(BigIntegers.ONE)), bigInteger4);
            }
            sshBuffer2.skipBlock();
            if (sshBuffer2.hasRemaining()) {
                throw new IllegalArgumentException("private key block has trailing data");
            }
        }
        if (asymmetricKeyParameter == null) {
            throw new IllegalArgumentException("unable to parse key");
        }
        return asymmetricKeyParameter;
    }
    
    private static boolean allIntegers(final ASN1Sequence asn1Sequence) {
        for (int i = 0; i < asn1Sequence.size(); ++i) {
            if (!(asn1Sequence.getObjectAt(i) instanceof ASN1Integer)) {
                return false;
            }
        }
        return true;
    }
    
    static {
        AUTH_MAGIC = Strings.toByteArray("openssh-key-v1\u0000");
    }
}
