package com.jscape.util.keystore;

import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DEROctetString;

import java.security.Key;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.interfaces.DSAKey;
import java.security.interfaces.ECKey;
import java.security.interfaces.RSAKey;
import java.util.List;

import static com.jscape.util.CollectionTools.castList;

/**
 * @author Alex Usun
 */
public class KeyTools {

    public static int bitLengthOf(Key key) {
        if (key instanceof RSAKey) {
            return ((RSAKey) key).getModulus().bitLength();
        } else if (key instanceof DSAKey) {
            return ((DSAKey) key).getParams().getP().bitLength();
        } else if (key instanceof ECKey) {
            return ((ECKey) key).getParams().getCurve().getField().getFieldSize();
        }

        return 0;
    }

    public static X509Certificate[] asX509(Certificate... certificates) {
        List<X509Certificate> x509Certificates = castList(certificates);
        return x509Certificates.toArray(new X509Certificate[0]);
    }

    public static byte[] subjectKeyIdentifierOf(X509Certificate certificate) {
        byte[] extensionData = certificate.getExtensionValue(X509ExtensionIdentifier.SUBJECT_KEY_IDENTIFIER.getId());

        if (extensionData == null) {
            return new byte[0];
        }

        try {
            byte[] identifierData = ((ASN1OctetString) ASN1Primitive.fromByteArray(extensionData)).getOctets();
            return ((DEROctetString) ASN1Primitive.fromByteArray(identifierData)).getOctets();
        } catch (Exception e) {
            return new byte[0];
        }
    }

    public static boolean selfSigned(X509Certificate certificate) {
        try {
            certificate.verify(certificate.getPublicKey());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean chained(X509Certificate parent, X509Certificate child) {
        if (!parent.getSubjectDN().equals(child.getIssuerDN()) || parent.equals(child)) {
            return false;
        }

        try {
            child.verify(parent.getPublicKey());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private KeyTools() {
        // empty
    }
}
