import java.io.ByteArrayInputStream;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

import javax.net.ssl.KeyManagerFactory;

public class SignatureTest2 {

    /*
    Certificate:
        Data:
            Version: 3 (0x2)
            Serial Number: 2021682774 (0x78806e56)
            Signature Algorithm: ecdsa-with-SHA384
            Issuer: CN = Test
            Validity
                Not Before: Nov 27 03:42:09 2018 GMT
                Not After : Feb 25 03:42:09 2019 GMT
            Subject: CN = Test
            Subject Public Key Info:
                Public Key Algorithm: id-ecPublicKey
                    Public-Key: (384 bit)
                    pub:
                        04:a4:04:c2:5b:f6:c3:69:c0:08:c7:9b:9f:94:cc:
                        41:97:d3:cb:6e:6a:c4:07:6e:d4:b7:09:3f:fe:f3:
                        a5:20:02:f6:25:0e:e5:dd:ed:96:01:b8:b4:12:fb:
                        5d:3c:d5:b2:1c:25:84:b1:58:1d:77:a0:52:f9:81:
                        58:e0:51:b8:f7:b4:77:02:ab:bc:74:ac:0e:c9:b7:
                        02:26:9b:13:82:48:d0:2d:af:a5:b7:17:6d:76:2f:
                        b9:49:d7:dc:b1:eb:38
                    ASN1 OID: secp384r1
                    NIST CURVE: P-384
            X509v3 extensions:
                X509v3 Subject Key Identifier: 
                    53:76:1A:30:AB:F6:D7:C4:A5:2B:FD:0F:D5:A9:14:22:7F:2D:B9:F7
        Signature Algorithm: ecdsa-with-SHA384
             30:66:02:31:00:9b:54:7a:32:30:e8:74:20:a6:36:93:42:ea:
             d5:05:be:01:cc:f1:2e:f1:ba:19:ca:42:33:76:01:16:42:4c:
             08:81:f2:fd:48:23:ff:f6:5f:77:02:ea:cc:78:66:d5:b6:02:
             31:00:f4:1e:4f:09:f2:78:91:6b:54:06:b2:d4:e5:85:71:57:
             85:23:ab:06:15:63:a1:27:31:2c:91:f4:af:9a:67:bf:b2:ab:
             ee:22:f5:4f:82:74:92:30:71:04:8d:a8:1d:5c
     */
    private static final String CERT =
            "-----BEGIN CERTIFICATE-----\n" + 
            "MIIBcjCB9qADAgECAgR4gG5WMAwGCCqGSM49BAMDBQAwDzENMAsGA1UEAxMEVGVz\n" + 
            "dDAeFw0xODExMjcwMzQyMDlaFw0xOTAyMjUwMzQyMDlaMA8xDTALBgNVBAMTBFRl\n" + 
            "c3QwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASkBMJb9sNpwAjHm5+UzEGX08tuasQH\n" + 
            "btS3CT/+86UgAvYlDuXd7ZYBuLQS+1081bIcJYSxWB13oFL5gVjgUbj3tHcCq7x0\n" + 
            "rA7JtwImmxOCSNAtr6W3F212L7lJ19yx6zijITAfMB0GA1UdDgQWBBRTdhowq/bX\n" + 
            "xKUr/Q/VqRQify259zAMBggqhkjOPQQDAwUAA2kAMGYCMQCbVHoyMOh0IKY2k0Lq\n" + 
            "1QW+AczxLvG6GcpCM3YBFkJMCIHy/Ugj//ZfdwLqzHhm1bYCMQD0Hk8J8niRa1QG\n" + 
            "stTlhXFXhSOrBhVjoScxLJH0r5pnv7Kr7iL1T4J0kjBxBI2oHVw=\n" + 
            "-----END CERTIFICATE-----";

    private static final String KEY =
            "ME4CAQAwEAYHKoZIzj0CAQYFK4EEACIENzA1AgEBBDA+0ooOXGufxQg1LFZRf9LT\n" + 
            "MV0mKkRhEqDxH+d3ULz8iF8lwaZJSZDiG3/c7LqdPTM=";

    private static final String ALIAS = "cert";

    public static void main(String[] args) throws Exception {
        runCase("EC", 384, "SHA256withECDSA");
        runCase("EC", 384, "SHA384withECDSA");
        runCase("EC", 384, "SHA512withECDSA");
        runCase("EC", 571, "SHA256withECDSA");
        runCase("EC", 571, "SHA384withECDSA");
        runCase("EC", 571, "SHA512withECDSA");
    }

    private static void runCase(String keyAlgo, int keySize, String signAlgo) {
        System.out.println("========== Case start ==========");
        System.out.printf("keyAlgo=%s, keySize=%d, signAlgo=%s%n", keyAlgo,
                keySize, signAlgo);
        try {
            signAndVerify(keyAlgo, keySize, signAlgo);
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
        System.out.println("========== Case end ==========");
    }

    private static void signAndVerify(String keyAlgo, int keySize,
            String signAlgo) throws Exception {
        KeyStore keyStore = createKeyStore();

        Signature signature = Signature.getInstance(signAlgo);
        System.out.println("Provider: " + signature.getProvider());

        signature.initSign((PrivateKey) keyStore.getKey(ALIAS, null));
        signature.update(new byte[100]);
        byte[] out = new byte[4096];
        System.out.println("Signing...");
        int length = signature.sign(out, 0, out.length);

        signature.initVerify(keyStore.getCertificate(ALIAS).getPublicKey());
        System.out.println("Verifying...");
        signature.verify(out, 0, length);
    }

    private static KeyStore createKeyStore() throws Exception {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(null, null);

        PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(
                Base64.getMimeDecoder().decode(KEY));
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        PrivateKey privKey = keyFactory.generatePrivate(privKeySpec);
        keyStore.setKeyEntry(ALIAS, privKey, null,
                new Certificate[] { cf.generateCertificate(
                        new ByteArrayInputStream(CERT.getBytes())) });
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
        kmf.init(keyStore, null);
        return keyStore;
    }
}
