/*
 * Copyright (c) 2019 Of Him Code Technology Studio
 * Jpom is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 * 			http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package cert;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.GlobalBouncyCastleProvider;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.PemUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.sun.security.cert.internal.x509.X509V1CertImpl;
import org.junit.Test;

import javax.security.cert.X509Certificate;
import java.io.File;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.util.Date;
import java.util.Enumeration;

/**
 * Created by bwcx_jzy on 2019/3/7.
 */
public class TestCert {

    static {
        //Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        GlobalBouncyCastleProvider.setUseBouncyCastle(false);
    }

    @Test
    public void testPfx() throws Exception {
        File file = FileUtil.file("D:\\System-Data\\Downloads\\download.jpom.top\\8215371_download.jpom.top_tomcat", "8215371_download.jpom.top.pfx");
        char[] password = "skkervmb".toCharArray();
        KeyStore keyStore = KeyUtil.readPKCS12KeyStore(file, password);
        String type = keyStore.getType();
//        keyStore.load(FileUtil.getInputStream(file), password);
        Enumeration<String> aliases = keyStore.aliases();
        if (aliases.hasMoreElements())// we are readin just one certificate.
        {
            String keyAlias = aliases.nextElement();
            System.out.println("alias=[" + keyAlias + "]");
            Certificate certificate = keyStore.getCertificate(keyAlias);
            System.out.println(certificate.getType());
            PrivateKey prikey = (PrivateKey) keyStore.getKey(keyAlias, password);
            {

                PublicKey pubkey = certificate.getPublicKey();
            }

            {
                X509Certificate cert = X509Certificate.getInstance(certificate.getEncoded());
                byte[] encoded = cert.getEncoded();
                System.out.println("指纹：" + SecureUtil.sha1().digestHex(encoded));
                Date notBefore = cert.getNotBefore();
                Date notAfter = cert.getNotAfter();
                BigInteger serialNumber = cert.getSerialNumber();
                if (cert instanceof X509V1CertImpl) {
                    X509V1CertImpl x509V1Cert = (X509V1CertImpl) cert;
                    java.security.cert.X509Certificate x509Certificate = x509V1Cert.getX509Certificate();
                    //AuthorityKeyIdentifier
                    byte[] extensionValue1 = x509Certificate.getExtensionValue("2.5.29.35");
                    // SubjectKeyIdentifier
                    byte[] extensionValue2 = x509Certificate.getExtensionValue("2.5.29.14");
                    System.out.println(HexUtil.encodeHexStr(ArrayUtil.sub(extensionValue1, 6, extensionValue1.length)));
                    System.out.println(HexUtil.encodeHexStr(ArrayUtil.sub(extensionValue2, 4, extensionValue2.length)));
                }
                System.out.println(serialNumber.toString(16));
                int version = cert.getVersion();
                Principal subjectDN = cert.getSubjectDN();
                Principal issuerDN = cert.getIssuerDN();
                String issuerDNName = issuerDN.getName();
                String subjectDNName = subjectDN.getName();
                String sigAlgOID = cert.getSigAlgOID();
                String sigAlgName = cert.getSigAlgName();
                System.out.println(serialNumber);
                System.out.println(notBefore + "  " + notAfter);
                System.out.println(sigAlgName);
                System.out.println(sigAlgOID);
                System.out.println(issuerDNName);
                System.out.println(subjectDNName);
            }
        }
//        KeyStore keyStore = KeyUtil.readJKSKeyStore(file, "skkervmb".toCharArray());
        System.out.println(keyStore);
    }

    @Test
    public void testKey() throws Exception {
        File file = FileUtil.file("D:\\System-Data\\Downloads\\download.jpom.top\\8215371_download.jpom.top_nginx", "8215371_download.jpom.top.pem");

        Certificate certificate = KeyUtil.readX509Certificate(FileUtil.getInputStream(file));
//        KeyStore keyStore = KeyUtil.readJKSKeyStore(file, "skkervmb".toCharArray());
        {
            X509Certificate cert = X509Certificate.getInstance(certificate.getEncoded());
            byte[] encoded = cert.getEncoded();
            System.out.println("指纹：" + SecureUtil.sha256().digestHex(encoded));
            Date notBefore = cert.getNotBefore();
            Date notAfter = cert.getNotAfter();
            BigInteger serialNumber = cert.getSerialNumber();
            System.out.println(certificate.getType());
            System.out.println(serialNumber);
            System.out.println(notBefore + "  " + notAfter);
        }
    }

    @Test
    public void testJks() throws Exception {
        File file = FileUtil.file("D:\\System-Data\\Downloads\\download.jpom.top\\8215371_download.jpom.top_jks", "8215371_download.jpom.top.jks");
        char[] password = "hibuvbsp".toCharArray();
        KeyStore keyStore = KeyUtil.readJKSKeyStore(file, password);
        keyStore.load(FileUtil.getInputStream(file), password);
        Enumeration<String> aliases = keyStore.aliases();
        if (aliases.hasMoreElements())// we are readin just one certificate.
        {
            String keyAlias = aliases.nextElement();
            System.out.println("alias=[" + keyAlias + "]");
            Certificate certificate = keyStore.getCertificate(keyAlias);
            PrivateKey prikey = (PrivateKey) keyStore.getKey(keyAlias, password);
            {

                PublicKey pubkey = certificate.getPublicKey();
            }
            {
                X509Certificate cert = X509Certificate.getInstance(certificate.getEncoded());
                byte[] encoded = cert.getEncoded();
                System.out.println("指纹：" + SecureUtil.sha256().digestHex(encoded));
                Date notBefore = cert.getNotBefore();
                Date notAfter = cert.getNotAfter();
                BigInteger serialNumber = cert.getSerialNumber();
                System.out.println(serialNumber);
                System.out.println(notBefore + "  " + notAfter);
            }
        }
//        KeyStore keyStore = KeyUtil.readJKSKeyStore(file, "skkervmb".toCharArray());
        System.out.println(keyStore);
    }

    @Test
    public void testCrt() throws Exception {
        PrivateKey privateKey = PemUtil.readPemPrivateKey(FileUtil.getInputStream("D:\\System-Data\\Downloads\\download.jpom.top\\8215371_download.jpom.top_apache\\8215371_download.jpom.top.key"));
        X509Certificate publicCert;
        PublicKey publicKey1;
        Certificate certificate1;

        {
            File file = FileUtil.file("D:\\System-Data\\Downloads\\download.jpom.top\\8215371_download.jpom.top_apache", "8215371_download.jpom.top_public.crt");
            certificate1 = KeyUtil.readX509Certificate(FileUtil.getInputStream(file));
            String certificate1Type = certificate1.getType();

            System.out.println(certificate1Type);
            {
                publicCert = X509Certificate.getInstance(certificate1.getEncoded());
                byte[] encoded = publicCert.getEncoded();
                System.out.println("指纹：" + SecureUtil.sha256().digestHex(encoded));
                System.out.println(publicCert.getIssuerDN().equals(publicCert.getSubjectDN()) + "  " + publicCert.getIssuerDN() + "  " + publicCert.getSubjectDN());
                Date notBefore = publicCert.getNotBefore();
                Date notAfter = publicCert.getNotAfter();
                BigInteger serialNumber = publicCert.getSerialNumber();
                System.out.println(serialNumber);
                System.out.println(notBefore + "  " + notAfter);
            }

            publicKey1 = certificate1.getPublicKey();
            RSA rsa = new RSA(privateKey, publicKey1);
            String str = "您好，Hutool";//测试字符串

            String encryptStr = rsa.encryptBase64(str, KeyType.PublicKey);
            String decryptStr = rsa.decryptStr(encryptStr, KeyType.PrivateKey);
            System.out.println(str.equals(decryptStr));

        }

        X509Certificate chainCert;
        {
            File file = FileUtil.file("D:\\System-Data\\Downloads\\download.jpom.top\\8215371_download.jpom.top_apache", "8215371_download.jpom.top_chain.crt");
            Certificate certificate = KeyUtil.readX509Certificate(FileUtil.getInputStream(file));
            String certificate2Type = certificate.getType();
            System.out.println(certificate2Type);
            {
                chainCert = X509Certificate.getInstance(certificate.getEncoded());
                System.out.println(chainCert.getIssuerDN().equals(chainCert.getSubjectDN()) + "  " + chainCert.getIssuerDN() + "  " + chainCert.getSubjectDN());
                Date notBefore = chainCert.getNotBefore();
                Date notAfter = chainCert.getNotAfter();
                BigInteger serialNumber = chainCert.getSerialNumber();
                System.out.println(serialNumber);
                System.out.println(notBefore + "  " + notAfter);
            }
            System.out.println(certificate.equals(certificate1));
            PublicKey publicKey = certificate.getPublicKey();
            System.out.println(publicKey.equals(publicKey1));
            System.out.println(certificate1.getEncoded().equals(certificate.getEncoded()));
//            RSA rsa = new RSA(privateKey, publicKey);
//            String str = "您好，Hutool";//测试字符串
//
//            String encryptStr = rsa.encryptBase64(str, KeyType.PublicKey);
//            String decryptStr = rsa.decryptStr(encryptStr, KeyType.PrivateKey);
//            System.out.println(str.equals(decryptStr));
        }
//        X509Certificate[] chain = new X509Certificate[]{publicCert, cert2};
        // Verify certificate chain
        publicCert.checkValidity();
        chainCert.checkValidity();

        publicCert.verify(chainCert.getPublicKey());
    }


    @Test
    public void testCa() throws Exception {
        File ca = FileUtil.file("D:\\System-Data\\Desktop\\ca", "ca.pem");
        File crt = FileUtil.file("D:\\System-Data\\Desktop\\ca", "cert.pem");
        File key = FileUtil.file("D:\\System-Data\\Desktop\\ca", "key.pem");

        PrivateKey privateKey = PemUtil.readPemPrivateKey(FileUtil.getInputStream(key));
        X509Certificate publicCert;
        PublicKey publicKey1;
        Certificate certificate1;

        {

            certificate1 = KeyUtil.readX509Certificate(FileUtil.getInputStream(crt));
            {
                publicCert = X509Certificate.getInstance(certificate1.getEncoded());
                byte[] encoded = publicCert.getEncoded();
                System.out.println("指纹：" + SecureUtil.sha256().digestHex(encoded));
                System.out.println(publicCert.getIssuerDN().equals(publicCert.getSubjectDN()) + "  " + publicCert.getIssuerDN() + "  " + publicCert.getSubjectDN());
                Date notBefore = publicCert.getNotBefore();
                Date notAfter = publicCert.getNotAfter();
                BigInteger serialNumber = publicCert.getSerialNumber();
                System.out.println(serialNumber);
                System.out.println(notBefore + "  " + notAfter);
            }

            publicKey1 = certificate1.getPublicKey();
            RSA rsa = new RSA(privateKey, publicKey1);
            String str = "您好，Hutool";//测试字符串

            String encryptStr = rsa.encryptBase64(str, KeyType.PublicKey);
            String decryptStr = rsa.decryptStr(encryptStr, KeyType.PrivateKey);
            System.out.println(str.equals(decryptStr));

        }

        X509Certificate chainCert;
        {

            Certificate certificate = KeyUtil.readX509Certificate(FileUtil.getInputStream(ca));
            {
                chainCert = X509Certificate.getInstance(certificate.getEncoded());
                System.out.println(chainCert.getIssuerDN().equals(chainCert.getSubjectDN()) + "  " + chainCert.getIssuerDN() + "  " + chainCert.getSubjectDN());
                Date notBefore = chainCert.getNotBefore();
                Date notAfter = chainCert.getNotAfter();
                BigInteger serialNumber = chainCert.getSerialNumber();
                System.out.println(chainCert.getSubjectDN().getName());
                System.out.println(serialNumber);
                System.out.println(notBefore + "  " + notAfter);
            }
            System.out.println(certificate.equals(certificate1));
            PublicKey publicKey = certificate.getPublicKey();
            System.out.println(publicKey.equals(publicKey1));
            System.out.println(certificate1.getEncoded().equals(certificate.getEncoded()));
//            RSA rsa = new RSA(privateKey, publicKey);
//            String str = "您好，Hutool";//测试字符串
//
//            String encryptStr = rsa.encryptBase64(str, KeyType.PublicKey);
//            String decryptStr = rsa.decryptStr(encryptStr, KeyType.PrivateKey);
//            System.out.println(str.equals(decryptStr));
        }
//        X509Certificate[] chain = new X509Certificate[]{publicCert, cert2};
        // Verify certificate chain
        publicCert.checkValidity();
        chainCert.checkValidity();

        publicCert.verify(chainCert.getPublicKey());
    }

    public void main(String[] args) {
//        HttpRequest request = HttpUtil.createPost("https://myssl.com/api/v1/tools/cert_decode");
//        request.form("certfile", new File("D:\\SystemDocument\\Desktop\\web_hulianwangjia\\full_chain.pem"));
//        request.form("type", "upload");
//        HttpResponse response = request.execute();
//        System.out.println(response.body());
//        D:\SystemDocument\Desktop

        PrivateKey privateKey = PemUtil.readPemPrivateKey(ResourceUtil.getStream("D:\\SystemDocument\\Desktop\\1979263_jpom.keepbx.cn.key"));
        PublicKey publicKey = PemUtil.readPemPublicKey(ResourceUtil.getStream("D:\\SystemDocument\\Desktop\\1979263_jpom.keepbx.cn.pem"));

        RSA rsa = new RSA(privateKey, publicKey);
        String str = "您好，Hutool";//测试字符串

        String encryptStr = rsa.encryptBase64(str, KeyType.PublicKey);
        String decryptStr = rsa.decryptStr(encryptStr, KeyType.PrivateKey);
        System.out.println(encryptStr);
        System.out.println(decryptStr);
        System.out.println(str.equals(decryptStr));
    }
}
