changeset 59343:c14e8bf10642

8209632: Develop new tests for EdDSA API Summary: New Tests for EdDSA Reviewed-by: ascarpino
author ssahoo
date Tue, 19 May 2020 02:36:17 -0700
parents 75ec2d59570d
children b1d6fe622f8e
files test/jdk/sun/security/ec/ed/EdCRLSign.java test/jdk/sun/security/ec/ed/EdDSAKeyCompatibility.java test/jdk/sun/security/ec/ed/EdDSAKeySize.java test/jdk/sun/security/ec/ed/EdDSANegativeTest.java test/jdk/sun/security/ec/ed/EdDSAParamSpec.java test/jdk/sun/security/ec/ed/EdDSAReuseTest.java test/jdk/sun/security/ec/ed/EdDSATest.java
diffstat 7 files changed, 1514 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ec/ed/EdCRLSign.java	Tue May 19 02:36:17 2020 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.SecureRandom;
+import java.security.spec.NamedParameterSpec;
+import java.util.Date;
+import sun.security.x509.X500Name;
+import sun.security.x509.X509CRLImpl;
+
+/*
+ * @test
+ * @bug 8209632
+ * @summary CRL Sign
+ * @modules java.base/sun.security.x509
+ * @run main EdCRLSign
+ */
+public class EdCRLSign {
+
+    private static final String ED25519 = "Ed25519";
+    private static final String ED448 = "Ed448";
+    private static final String OIDN25519 = "1.3.101.112";
+    private static final String OID25519 = "OID.1.3.101.112";
+    private static final String OIDN448 = "1.3.101.113";
+    private static final String OID448 = "OID.1.3.101.113";
+    private static final String PROVIDER = "SunEC";
+    private static final SecureRandom S_RND = new SecureRandom(new byte[]{0x1});
+
+    public static void main(String[] args) throws Exception {
+
+        for (boolean initWithRandom : new boolean[]{true, false}) {
+            // Default Parameter
+            test(PROVIDER, ED25519, null, initWithRandom);
+            test(PROVIDER, ED448, null, initWithRandom);
+
+            // With named parameter
+            test(PROVIDER, ED25519, ED25519, initWithRandom);
+            test(PROVIDER, OIDN25519, ED25519, initWithRandom);
+            test(PROVIDER, OID25519, ED25519, initWithRandom);
+            test(PROVIDER, ED448, ED448, initWithRandom);
+            test(PROVIDER, OIDN448, ED448, initWithRandom);
+            test(PROVIDER, OID448, ED448, initWithRandom);
+
+            // With size parameter
+            test(PROVIDER, ED25519, 255, initWithRandom);
+            test(PROVIDER, OIDN25519, 255, initWithRandom);
+            test(PROVIDER, OID25519, 255, initWithRandom);
+            test(PROVIDER, ED448, 448, initWithRandom);
+            test(PROVIDER, OIDN448, 448, initWithRandom);
+            test(PROVIDER, OID448, 448, initWithRandom);
+        }
+    }
+
+    // Test CRL signature using a KeyPair.
+    private static void test(String provider, String name, Object param,
+            boolean initWithRandom) throws Exception {
+
+        System.out.printf("Case Algo:%s, Param:%s, Intitiate with random:%s%n",
+                name, param, initWithRandom);
+        KeyPair kp = genKeyPair(provider, name, param, initWithRandom);
+        X509CRLImpl crl = new X509CRLImpl(
+                new X500Name("CN=Issuer"), new Date(), new Date());
+        crl.sign(kp.getPrivate(), name);
+        crl.verify(kp.getPublic());
+        System.out.println("Passed.");
+    }
+
+    private static KeyPair genKeyPair(String provider, String name,
+            Object param, boolean initWithRandom) throws Exception {
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(name, provider);
+        if (initWithRandom) {
+            if (param instanceof Integer) {
+                kpg.initialize((Integer) param, S_RND);
+            } else if (param instanceof String) {
+                kpg.initialize(new NamedParameterSpec((String) param), S_RND);
+            }
+        } else {
+            if (param instanceof Integer) {
+                kpg.initialize((Integer) param);
+            } else if (param instanceof String) {
+                kpg.initialize(new NamedParameterSpec((String) param));
+            }
+        }
+        return kpg.generateKeyPair();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ec/ed/EdDSAKeyCompatibility.java	Tue May 19 02:36:17 2020 -0700
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.util.Base64;
+import sun.security.util.DerValue;
+import java.security.interfaces.EdECPrivateKey;
+import java.security.interfaces.EdECPublicKey;
+import java.security.spec.EdECPrivateKeySpec;
+import java.security.spec.EdECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.NamedParameterSpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+/*
+ * @test
+ * @bug 8209632
+ * @summary OpenSSL generated compatibility test with EDDSA Java.
+ * @modules java.base/sun.security.util
+ * @run main EdDSAKeyCompatibility
+ */
+public class EdDSAKeyCompatibility {
+
+    private static final String EDDSA = "EdDSA";
+    private static final String ED25519 = "Ed25519";
+    private static final String ED448 = "Ed448";
+    private static final String PROVIDER = "SunEC";
+
+    public static void main(String[] args) throws Exception {
+
+        boolean result = true;
+        result &= validateCert(EDDSA, PROVIDER, ED25519CERT);
+        result &= validateCert(EDDSA, PROVIDER, ED448CERT);
+        result &= validateCert(ED25519, PROVIDER, ED25519CERT);
+        result &= validateCert(ED448, PROVIDER, ED448CERT);
+
+        result &= validatePrivate(ED25519, PROVIDER, ED25519KEY);
+        result &= validatePrivate(ED448, PROVIDER, ED448KEY);
+
+        if (!result) {
+            throw new RuntimeException("Some test cases failed");
+        }
+    }
+
+    private static boolean validatePrivate(String algorithm, String provider,
+            String key) {
+
+        try {
+            KeyFactory kf = KeyFactory.getInstance(algorithm, provider);
+            PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(
+                    Base64.getMimeDecoder().decode(key));
+            EdECPrivateKey privKey
+                    = (EdECPrivateKey) kf.generatePrivate(privSpec);
+            checkPrivKeyFormat(privKey.getEncoded());
+
+            NamedParameterSpec namedSpec = new NamedParameterSpec(algorithm);
+            EdECPrivateKeySpec edprivSpec = new EdECPrivateKeySpec(
+                    namedSpec, privKey.getBytes().get());
+            EdECPrivateKey privKey1
+                    = (EdECPrivateKey) kf.generatePrivate(edprivSpec);
+            checkPrivKeyFormat(privKey1.getEncoded());
+            EdECPrivateKey privKey2 = (EdECPrivateKey) kf.translateKey(privKey);
+            checkPrivKeyFormat(privKey2.getEncoded());
+            equals(privKey, privKey1);
+            equals(privKey, privKey2);
+        } catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException
+                | NoSuchProviderException | InvalidKeyException e) {
+            e.printStackTrace(System.out);
+            return false;
+        }
+        System.out.println("PASSED - validatePrivate");
+        return true;
+    }
+
+    private static boolean validateCert(String algorithm, String provider,
+            String certificate) {
+
+        try {
+            CertificateFactory cf = CertificateFactory.getInstance("X.509");
+            Certificate cert = cf.generateCertificate(
+                    new ByteArrayInputStream(certificate.getBytes()));
+            System.out.println(cert);
+            KeyFactory kf = KeyFactory.getInstance(algorithm, provider);
+            X509EncodedKeySpec pubSpec = kf.getKeySpec(
+                    cert.getPublicKey(), X509EncodedKeySpec.class);
+            EdECPublicKey pubKey = (EdECPublicKey) kf.generatePublic(pubSpec);
+            EdECPublicKeySpec edpubSpec = kf.getKeySpec(
+                    cert.getPublicKey(), EdECPublicKeySpec.class);
+            EdECPublicKey pubKey1 = (EdECPublicKey) kf.generatePublic(edpubSpec);
+            EdECPublicKey pubKey2 = (EdECPublicKey) kf.translateKey(pubKey);
+            equals(pubKey, pubKey1);
+            equals(pubKey, pubKey2);
+            equals(pubKey, cert.getPublicKey());
+        } catch (CertificateException | NoSuchAlgorithmException
+                | InvalidKeySpecException | NoSuchProviderException
+                | InvalidKeyException e) {
+            e.printStackTrace(System.out);
+            return false;
+        }
+        System.out.println("PASSED - validateCert");
+        return true;
+    }
+
+    private static void checkPrivKeyFormat(byte[] key) throws IOException {
+
+        // key value should be nested octet strings
+        DerValue val = new DerValue(new ByteArrayInputStream(key));
+        BigInteger version = val.data.getBigInteger();
+        DerValue algId = val.data.getDerValue();
+        byte[] keyValue = val.data.getOctetString();
+        val = new DerValue(new ByteArrayInputStream(keyValue));
+        if (val.tag != DerValue.tag_OctetString) {
+            throw new RuntimeException("incorrect format");
+        }
+    }
+
+    private static void equals(Object actual, Object expected) {
+        if (!actual.equals(expected)) {
+            throw new RuntimeException(String.format("Actual: %s, Expected: %s",
+                    actual, expected));
+        }
+    }
+
+    // Following EdDSA Certificates/Keys are generated through openssl_1.1.1d
+
+    /*
+     * Certificate:
+     *  Data:
+     *     Version: 3 (0x2)
+     *     Serial Number:
+     *         1d:d3:87:b9:e4:c6:9e:4a:5c:78:a8:f0:c7:9b:37:be:1e:31:dd:20
+     *     Signature Algorithm: ED25519
+     *     Issuer: C = US, ST = CA, L = SCA, O = test, OU = test, CN = localhost
+     *     Validity
+     *         Not Before: Mar  6 05:55:31 2020 GMT
+     *         Not After : Mar  1 05:55:31 2040 GMT
+     *     Subject: C = US, ST = CA, L = SCA, O = test, OU = test, CN = localhost
+     *     Subject Public Key Info:
+     *         Public Key Algorithm: ED25519
+     */
+    private static final String ED25519KEY
+            = "MC4CAQAwBQYDK2VwBCIEIP8xGaQTMh+I+59I66AaN+B4qnY1oWGjPwbSY4r+D08f";
+
+    private static final String ED25519CERT
+            = "-----BEGIN CERTIFICATE-----\n"
+            + "MIIByTCCAXugAwIBAgIUHdOHueTGnkpceKjwx5s3vh4x3SAwBQYDK2VwMFoxCzAJ\n"
+            + "BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0NBMQ0wCwYDVQQKDAR0\n"
+            + "ZXN0MQ0wCwYDVQQLDAR0ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMjAwMzA2\n"
+            + "MDU1NTMxWhcNNDAwMzAxMDU1NTMxWjBaMQswCQYDVQQGEwJVUzELMAkGA1UECAwC\n"
+            + "Q0ExDDAKBgNVBAcMA1NDQTENMAsGA1UECgwEdGVzdDENMAsGA1UECwwEdGVzdDES\n"
+            + "MBAGA1UEAwwJbG9jYWxob3N0MCowBQYDK2VwAyEAdqQ4Nduhbl+ShGeKdOryVMKy\n"
+            + "1t1LjyjPyCBC+gSk0eCjUzBRMB0GA1UdDgQWBBS01/VQEzwkFNRW/esQxaB6+uId\n"
+            + "8jAfBgNVHSMEGDAWgBS01/VQEzwkFNRW/esQxaB6+uId8jAPBgNVHRMBAf8EBTAD\n"
+            + "AQH/MAUGAytlcANBAEJkLuNfyVws7HKqHL7oDqQkp5DSwh+bGjrr2p4zSvs5PZ8o\n"
+            + "jRXWV0SMt/MB+90ubMD5tL7H7J6DR5PUFBIwGwc=\n"
+            + "-----END CERTIFICATE-----";
+
+    /*
+     * Certificate:
+     *  Data:
+     *     Version: 3 (0x2)
+     *     Serial Number:
+     *         42:eb:8c:a2:a0:6f:8e:5a:a5:f8:7c:72:c1:f1:8b:7e:44:1b:37:80
+     *     Signature Algorithm: ED448
+     *     Issuer: C = US, ST = CA, L = SCA, O = test, OU = test, CN = localhost
+     *     Validity
+     *         Not Before: Mar  6 05:57:42 2020 GMT
+     *         Not After : Mar  1 05:57:42 2040 GMT
+     *     Subject: C = US, ST = CA, L = SCA, O = test, OU = test, CN = localhost
+     *     Subject Public Key Info:
+     *         Public Key Algorithm: ED448
+     */
+    private static final String ED448KEY
+            = "MEcCAQAwBQYDK2VxBDsEOdG4lrYO0xBaf3aJWYMZ8XAxitA1zV4/ghG8wPBag8HQ"
+            + "XN+3OmS8wR1KfeGQysHQr3JHco3Mwiaz8w==";
+
+    private static final String ED448CERT
+            = "-----BEGIN CERTIFICATE-----\n"
+            + "MIICFDCCAZSgAwIBAgIUQuuMoqBvjlql+HxywfGLfkQbN4AwBQYDK2VxMFoxCzAJ\n"
+            + "BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0NBMQ0wCwYDVQQKDAR0\n"
+            + "ZXN0MQ0wCwYDVQQLDAR0ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMjAwMzA2\n"
+            + "MDU1NzQyWhcNNDAwMzAxMDU1NzQyWjBaMQswCQYDVQQGEwJVUzELMAkGA1UECAwC\n"
+            + "Q0ExDDAKBgNVBAcMA1NDQTENMAsGA1UECgwEdGVzdDENMAsGA1UECwwEdGVzdDES\n"
+            + "MBAGA1UEAwwJbG9jYWxob3N0MEMwBQYDK2VxAzoAfKlXpT0ymcvz2Gp+8HLzBpaz\n"
+            + "5mQqMaDbGmcq8gSIdeEUtVmv4OplE+4GSnrbJnEn99LQdbanL/MAo1MwUTAdBgNV\n"
+            + "HQ4EFgQUXkm9LVUkB0f/1MiPFjQPHGJ8THIwHwYDVR0jBBgwFoAUXkm9LVUkB0f/\n"
+            + "1MiPFjQPHGJ8THIwDwYDVR0TAQH/BAUwAwEB/zAFBgMrZXEDcwDvE3LKCg1bTjHi\n"
+            + "MI1EiMqZN3PJYVBsztecBXm3ELDlT+F0Z1H2vjaROkJc8PdpUOxyed1xDjwq3IB/\n"
+            + "nYYJNVyt6Dy3d12kl77ev+YMD83OuqM6F5O6MdDUxYQu9u3NasZAU5FQ6zklWWpI\n"
+            + "8jCPtOvcAQA=\n"
+            + "-----END CERTIFICATE-----";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ec/ed/EdDSAKeySize.java	Tue May 19 02:36:17 2020 -0700
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import static javax.crypto.Cipher.PRIVATE_KEY;
+import static javax.crypto.Cipher.PUBLIC_KEY;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.interfaces.EdECPrivateKey;
+import java.security.interfaces.EdECPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.security.spec.EdECPrivateKeySpec;
+import java.security.spec.EdECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.NamedParameterSpec;
+import java.util.Arrays;
+import jdk.test.lib.Convert;
+
+/*
+ * @test
+ * @bug 8209632
+ * @summary Verify KeyLength for EDDSA, ED25519, ED448.
+ * @library /test/lib
+ * @build jdk.test.lib.Convert
+ * @run main EdDSAKeySize
+ */
+public class EdDSAKeySize {
+
+    private static final String EDDSA = "EDDSA";
+    private static final String ED25519 = "ED25519";
+    private static final String ED448 = "ED448";
+    private static final String OIDN25519 = "1.3.101.112";
+    private static final String OID25519 = "OID.1.3.101.112";
+    private static final String OIDN448 = "1.3.101.113";
+    private static final String OID448 = "OID.1.3.101.113";
+    private static final String PROVIDER = "SunEC";
+    private static final SecureRandom RND = new SecureRandom(new byte[]{0x1});
+
+    public static void main(String[] args) throws Exception {
+
+        for (boolean initWithRandom : new boolean[]{true, false}) {
+
+            // As per rfc8032 the generated keysize for ED25519 is
+            // 32 octets(256 bits) and ED448 is 57 octets(456 bits).
+            // Case with default parameter
+            testKeyAttributes(PROVIDER, EDDSA, initWithRandom, null, 256);
+            testKeyAttributes(PROVIDER, ED25519, initWithRandom, null, 256);
+            testKeyAttributes(PROVIDER, ED448, initWithRandom, null, 456);
+
+            // With named parameter
+            testKeyAttributes(PROVIDER, EDDSA, initWithRandom, ED25519, 256);
+            testKeyAttributes(PROVIDER, ED25519, initWithRandom, ED25519, 256);
+            testKeyAttributes(PROVIDER, OIDN25519, initWithRandom, ED25519, 256);
+            testKeyAttributes(PROVIDER, OID25519, initWithRandom, ED25519, 256);
+            testKeyAttributes(PROVIDER, ED448, initWithRandom, ED448, 456);
+            testKeyAttributes(PROVIDER, OIDN448, initWithRandom, ED448, 456);
+            testKeyAttributes(PROVIDER, OID448, initWithRandom, ED448, 456);
+
+            // With size parameter
+            testKeyAttributes(PROVIDER, EDDSA, initWithRandom, 255, 256);
+            testKeyAttributes(PROVIDER, ED25519, initWithRandom, 255, 256);
+            testKeyAttributes(PROVIDER, OIDN25519, initWithRandom, 255, 256);
+            testKeyAttributes(PROVIDER, OID25519, initWithRandom, 255, 256);
+            testKeyAttributes(PROVIDER, ED448, initWithRandom, 448, 456);
+            testKeyAttributes(PROVIDER, OIDN448, initWithRandom, 448, 456);
+            testKeyAttributes(PROVIDER, OID448, initWithRandom, 448, 456);
+        }
+    }
+
+    /**
+     * Test standard Key attributes.
+     */
+    private static void testKeyAttributes(String provider, String name,
+            boolean initWithRandom, Object param, int keySize) throws Exception {
+
+        System.out.printf("Case name: %s, param: %s, Expected keysize: %s, "
+                + "Initiate with random: %s%n", name, param, keySize,
+                initWithRandom);
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(name, provider);
+        if (initWithRandom) {
+            if (param instanceof Integer) {
+                kpg.initialize((Integer) param, RND);
+            } else if (param instanceof String) {
+                kpg.initialize(new NamedParameterSpec((String) param), RND);
+            }
+        } else {
+            if (param instanceof Integer) {
+                kpg.initialize((Integer) param);
+            } else if (param instanceof String) {
+                kpg.initialize(new NamedParameterSpec((String) param));
+            }
+        }
+        KeyPair kp = kpg.generateKeyPair();
+        NamedParameterSpec namedSpec = getNamedParamSpec(name);
+
+        // Verify original PrivateKey with it's different representation
+        Key[] privs = manipulateKey(provider, name, PRIVATE_KEY,
+                kp.getPrivate(), namedSpec);
+        Arrays.stream(privs).forEach(
+                priv -> testPrivateKey((EdECPrivateKey) kp.getPrivate(),
+                        (EdECPrivateKey) priv, keySize));
+
+        // Verify original PublicKey with it's different representation
+        Key[] pubs = manipulateKey(provider, name, PUBLIC_KEY,
+                kp.getPublic(), namedSpec);
+        Arrays.stream(pubs).forEach(
+                pub -> testPublicKey((EdECPublicKey) kp.getPublic(),
+                        (EdECPublicKey) pub));
+        System.out.println("Passed.");
+    }
+
+    private static NamedParameterSpec getNamedParamSpec(String algo) {
+        NamedParameterSpec namedSpec = switch (algo) {
+            case EDDSA
+                , OIDN25519, OID25519 -> new NamedParameterSpec(ED25519);
+            case OIDN448
+                , OID448 -> new NamedParameterSpec(ED448);
+            default->
+                new NamedParameterSpec(algo);
+        };
+            return namedSpec;
+    }
+
+    private static Key[] manipulateKey(String provider, String algo, int type,
+            Key key, NamedParameterSpec namedSpec)
+            throws NoSuchAlgorithmException, InvalidKeySpecException,
+            NoSuchProviderException, InvalidKeyException {
+
+        KeyFactory kf = KeyFactory.getInstance(algo, provider);
+        switch (type) {
+            case PUBLIC_KEY:
+                return new Key[]{
+                    kf.generatePublic(new X509EncodedKeySpec(key.getEncoded())),
+                    kf.generatePublic(kf.getKeySpec(
+                    key, EdECPublicKeySpec.class)),
+                    kf.generatePublic(new EdECPublicKeySpec(namedSpec,
+                    ((EdECPublicKey) key).getPoint())),
+                    kf.translateKey(key)
+                };
+            case PRIVATE_KEY:
+                return new Key[]{
+                    kf.generatePrivate(new PKCS8EncodedKeySpec(key.getEncoded())),
+                    kf.generatePrivate(
+                    kf.getKeySpec(key, EdECPrivateKeySpec.class)),
+                    kf.generatePrivate(new EdECPrivateKeySpec(namedSpec,
+                    ((EdECPrivateKey) key).getBytes().get())),
+                    kf.translateKey(key)
+                };
+        }
+        throw new RuntimeException("We shouldn't reach here");
+    }
+
+    /**
+     * Basic PrivateKey Test cases
+     */
+    private static void testPrivateKey(EdECPrivateKey orig,
+            EdECPrivateKey generated, int size) {
+
+        equals(orig.getBytes().get().length * 8, size);
+        equals(generated.getBytes().get().length * 8, size);
+        equals(orig.getBytes().get(), generated.getBytes().get());
+        equals(orig.getFormat(), generated.getFormat());
+        equals(orig.getEncoded(), generated.getEncoded());
+        equals(((NamedParameterSpec) orig.getParams()).getName(),
+                ((NamedParameterSpec) generated.getParams()).getName());
+    }
+
+    /**
+     * Basic PublicKey Test cases
+     */
+    private static void testPublicKey(EdECPublicKey orig,
+            EdECPublicKey generated) {
+
+        equals(orig.getPoint().getY(), generated.getPoint().getY());
+        equals(orig.getPoint().isXOdd(), generated.getPoint().isXOdd());
+        equals(orig.getFormat(), generated.getFormat());
+        equals(orig.getEncoded(), generated.getEncoded());
+        equals(((NamedParameterSpec) orig.getParams()).getName(),
+                ((NamedParameterSpec) generated.getParams()).getName());
+    }
+
+    private static void equals(Object actual, Object expected) {
+        if (!actual.equals(expected)) {
+            throw new RuntimeException(String.format("Actual: %s, Expected: %s",
+                    actual, expected));
+        }
+    }
+
+    private static void equals(byte[] actual, byte[] expected) {
+        if (!Arrays.equals(actual, expected)) {
+            throw new RuntimeException(String.format("Actual array: %s, "
+                    + "Expected array:%s", Convert.byteArrayToHexString(actual),
+                    Convert.byteArrayToHexString(expected)));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ec/ed/EdDSANegativeTest.java	Tue May 19 02:36:17 2020 -0700
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.interfaces.EdECPrivateKey;
+import java.security.interfaces.EdECPublicKey;
+import java.security.spec.EdDSAParameterSpec;
+import java.util.Arrays;
+import jdk.test.lib.Convert;
+
+/*
+ * @test
+ * @bug 8209632
+ * @summary Negative cases for EDDSA.
+ * @library /test/lib
+ * @build jdk.test.lib.Convert
+ * @run main EdDSANegativeTest
+ */
+public class EdDSANegativeTest {
+
+    private static final String EDDSA = "EdDSA";
+    private static final String ED25519 = "Ed25519";
+    private static final String ED448 = "Ed448";
+    private static final String PROVIDER = "SunEC";
+    private static final String OTHER = "other";
+    private static final byte[] MSG = "TEST".getBytes();
+
+    public static void main(String[] args) throws Exception {
+        byName();
+        byParam();
+        byInvalidKey();
+        byInvalidKeyType();
+    }
+
+    private static void byName() throws Exception {
+
+        for (String name : new String[]{null, "", "EDDSA", "eddsa", "EDdsa",
+            EDDSA, ED25519, "ed25519", "ED25519", ED448, "eD448", "ED448",
+            "ed448", OTHER}) {
+            try {
+                KeyPair kp = genKeyPair(name);
+                KeyFactory kf = KeyFactory.getInstance(name, PROVIDER);
+                EdECPrivateKey edPri
+                        = (EdECPrivateKey) kf.translateKey(kp.getPrivate());
+                EdECPublicKey edPub
+                        = (EdECPublicKey) kf.translateKey(kp.getPublic());
+                Signature sig = Signature.getInstance(name, PROVIDER);
+                byte[] computedSig = sign(sig, edPri, MSG);
+                if (!verify(sig, edPub, MSG, computedSig)) {
+                    throw new RuntimeException("Signature verification failed");
+                }
+                if (name == null || "".equals(name)) {
+                    throw new RuntimeException(
+                            "Should not reach here for algo: " + name);
+                }
+                System.out.println("Passed: byName: " + name);
+            } catch (NullPointerException e) {
+                if (name != null) {
+                    throw new RuntimeException(
+                            "Unknown issue with algo name: " + name, e);
+                }
+            } catch (NoSuchAlgorithmException e) {
+                if (!("".equals(name) || OTHER.equals(name))) {
+                    throw new RuntimeException(
+                            "Unknown issue with algo name: " + name, e);
+                }
+            }
+        }
+    }
+
+    private static void byParam() throws Exception {
+        testParam(EDDSA);
+        testParam(ED25519);
+        testParam(ED448);
+    }
+
+    private static void byInvalidKey() throws Exception {
+        testInvalidKey(EDDSA);
+        testInvalidKey(ED25519);
+        testInvalidKey(ED448);
+    }
+
+    private static void byInvalidKeyType() throws Exception {
+        testInvalidKeyType(EDDSA);
+        testInvalidKeyType(ED25519);
+        testInvalidKeyType(ED448);
+    }
+
+    /**
+     * Test Signature.
+     */
+    private static void testParam(String name) throws Exception {
+
+        KeyPair kp = genKeyPair(name);
+        Signature sig = Signature.getInstance(name, PROVIDER);
+        // Set initial paramter to generate a signature
+        EdDSAParameterSpec initParam
+                = new EdDSAParameterSpec(true, "testContext".getBytes());
+        sig.setParameter(initParam);
+        byte[] computedSig = sign(sig, kp.getPrivate(), MSG);
+        // Signature should not get verified other than same parameter
+        // which is set through the signature instance.
+        for (boolean preHash : new boolean[]{true, false}) {
+            // Test case with prehash as parameter without context set.
+            verify(sig, kp.getPublic(), MSG, new EdDSAParameterSpec(preHash),
+                    initParam, computedSig);
+            // Test Case with Context combined of different sizes.
+            // As per rfc8032, value of context is maximum of 255 octet
+            for (byte[] context : new byte[][]{{}, "other".getBytes(),
+            new byte[255], new byte[500]}) {
+                System.out.printf("Testing signature for name: %s, algorithm "
+                        + "spec: (prehash:%s, context:%s)%n", name, preHash,
+                        Convert.byteArrayToHexString(context));
+                try {
+                    verify(sig, kp.getPublic(), MSG,
+                            new EdDSAParameterSpec(preHash, context),
+                            initParam, computedSig);
+                } catch (InvalidParameterException e) {
+                    if (context.length <= 255) {
+                        throw new RuntimeException("Should not throw exception "
+                                + "when context size <= 255 octet: "
+                                + context.length);
+                    }
+                }
+            }
+        }
+    }
+
+    private static void testInvalidKey(String name) throws Exception {
+        KeyPair kp = genKeyPair(name);
+        KeyPair kp1 = genKeyPair(name);
+        Signature sig = Signature.getInstance(name, PROVIDER);
+        byte[] computedSig = sign(sig, kp.getPrivate(), MSG);
+        if (verify(sig, kp1.getPublic(), MSG, computedSig)) {
+            throw new RuntimeException("Signature verification failed "
+                    + "for unpaired key.");
+        }
+        System.out.println("Passed: testInvalidKey: " + name);
+    }
+
+    private static void testInvalidKeyType(String name) throws Exception {
+
+        KeyFactory kf = KeyFactory.getInstance(name, PROVIDER);
+        try {
+            kf.translateKey(new InvalidPrivateKey());
+        } catch (InvalidKeyException e) {
+            // Expected exception and not to be handled
+        }
+        try {
+            kf.translateKey(new InvalidPublicKey());
+        } catch (InvalidKeyException e) {
+            // Expected exception and not to be handled
+        }
+        System.out.println("Passed: testInvalidKeyType: " + name);
+    }
+
+    private static KeyPair genKeyPair(String name) throws Exception {
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(name, PROVIDER);
+        return kpg.generateKeyPair();
+    }
+
+    private static byte[] sign(Signature sig, PrivateKey priKey, byte[] msg)
+            throws Exception {
+        sig.initSign(priKey);
+        sig.update(msg);
+        return sig.sign();
+    }
+
+    private static boolean verify(Signature sig, PublicKey pubKey, byte[] msg,
+            byte[] sign) throws Exception {
+        sig.initVerify(pubKey);
+        sig.update(msg);
+        return sig.verify(sign);
+    }
+
+    private static void verify(Signature sig, PublicKey pubKey, byte[] msg,
+            EdDSAParameterSpec params, EdDSAParameterSpec initParam,
+            byte[] computedSig) throws Exception {
+
+        sig.setParameter(params);
+        if (verify(sig, pubKey, msg, computedSig)) {
+            byte[] context = params.getContext().isPresent()
+                    ? params.getContext().get() : null;
+            byte[] initContext = initParam.getContext().isPresent()
+                    ? initParam.getContext().get() : null;
+            boolean preHash = params.isPrehash();
+            boolean initPreHash = initParam.isPrehash();
+            // The signature should not get verified with other parameters
+            // set through signature instance.
+            if (!(equals(context, initContext) && equals(preHash, initPreHash))) {
+                throw new RuntimeException(String.format("Signature verification"
+                        + " success with different param context(actual:%s, "
+                        + "expected:%s), Prehash(actual:%s, expected:%s)",
+                        Convert.byteArrayToHexString(context),
+                        Convert.byteArrayToHexString(initContext),
+                        preHash, initPreHash));
+            } else {
+                System.out.println("Atleast a case matched");
+            }
+        }
+    }
+
+    private static boolean equals(Object actual, Object expected) {
+        if (actual == expected) {
+            return true;
+        }
+        if (actual == null || expected == null) {
+            return false;
+        }
+        boolean equals = actual.equals(expected);
+        if (!equals) {
+            throw new RuntimeException(String.format("Actual: %s, Expected: %s",
+                    actual, expected));
+        }
+        return equals;
+    }
+
+    private static boolean equals(byte[] actual, byte[] expected) {
+        if (actual == expected) {
+            return true;
+        }
+        if (actual == null || expected == null) {
+            return false;
+        }
+        boolean equals = Arrays.equals(actual, expected);
+        if (!equals) {
+            throw new RuntimeException(String.format("Actual array: %s, "
+                    + "Expected array:%s", Convert.byteArrayToHexString(actual),
+                    Convert.byteArrayToHexString(expected)));
+        }
+        return equals;
+    }
+
+    private static class InvalidPrivateKey implements PrivateKey {
+
+        @Override
+        public String getAlgorithm() {
+            return "test";
+        }
+
+        @Override
+        public String getFormat() {
+            return "test";
+        }
+
+        @Override
+        public byte[] getEncoded() {
+            return "test".getBytes();
+        }
+
+    }
+
+    private static class InvalidPublicKey implements PublicKey {
+
+        @Override
+        public String getAlgorithm() {
+            return "test";
+        }
+
+        @Override
+        public String getFormat() {
+            return "test";
+        }
+
+        @Override
+        public byte[] getEncoded() {
+            return "test".getBytes();
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ec/ed/EdDSAParamSpec.java	Tue May 19 02:36:17 2020 -0700
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.spec.EdDSAParameterSpec;
+import java.util.Arrays;
+import jdk.test.lib.Convert;
+
+/*
+ * @test
+ * @bug 8209632
+ * @summary Test EdDSAParameterSpec.
+ * @library /test/lib
+ * @build jdk.test.lib.Convert
+ * @run main EdDSAParamSpec
+ */
+public class EdDSAParamSpec {
+
+    private static final String EDDSA = "EdDSA";
+    private static final String ED25519 = "Ed25519";
+    private static final String ED448 = "Ed448";
+    private static final String PROVIDER = "SunEC";
+    private static final byte[] MSG = "TEST".getBytes();
+    private static final SecureRandom RND = new SecureRandom(new byte[]{0x1});
+
+    public static void main(String[] args) throws Exception {
+
+        testParam(PROVIDER, EDDSA);
+        testParam(PROVIDER, ED25519);
+        testParam(PROVIDER, ED448);
+    }
+
+    /**
+     * Test Signature.
+     */
+    private static void testParam(String provider, String name)
+            throws Exception {
+
+        KeyPair kp = genKeyPair(provider, name);
+        Signature sig = Signature.getInstance(name, provider);
+        EdDSAParameterSpec initParam
+                = new EdDSAParameterSpec(true, "testContext".getBytes());
+        sig.setParameter(initParam);
+        byte[] origSign = sign(sig, kp.getPrivate(), MSG);
+        for (boolean preHash : new boolean[]{true, false}) {
+            System.out.printf("Testing signature for name: %s,"
+                    + " algorithm spec: (prehash:%s)%n", name, preHash);
+            verifyPublic(sig, kp.getPublic(), MSG,
+                    new EdDSAParameterSpec(preHash), initParam, origSign);
+            // Test Case with Context size combined.
+            // As per rfc8032, value of context is maximum of 255 octet
+            byte[] maxCtx = new byte[255];
+            RND.nextBytes(maxCtx);
+            for (byte[] context : new byte[][]{"others".getBytes(), maxCtx}) {
+                System.out.printf("Testing signature for name: %s,"
+                        + " algorithm spec: (prehash:%s, context:%s)%n",
+                        name, preHash, Convert.byteArrayToHexString(context));
+                EdDSAParameterSpec params
+                        = new EdDSAParameterSpec(preHash, context);
+                verifyPublic(sig, kp.getPublic(), MSG, params, initParam,
+                        origSign);
+            }
+        }
+        System.out.println("Passed.");
+    }
+
+    private static KeyPair genKeyPair(String provider, String name)
+            throws Exception {
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(name, provider);
+        return kpg.generateKeyPair();
+    }
+
+    private static byte[] sign(Signature sig, PrivateKey priKey, byte[] msg)
+            throws Exception {
+
+        sig.initSign(priKey);
+        sig.update(msg);
+        return sig.sign();
+    }
+
+    private static boolean verify(Signature sig, PublicKey pubKey, byte[] msg,
+            byte[] sign) throws Exception {
+
+        sig.initVerify(pubKey);
+        sig.update(msg);
+        return sig.verify(sign);
+    }
+
+    private static void verifyPublic(Signature sig, PublicKey pubKey,
+            byte[] msg, EdDSAParameterSpec params, EdDSAParameterSpec initParam,
+            byte[] origSign) throws Exception {
+
+        sig.setParameter(params);
+        if (verify(sig, pubKey, msg, origSign)) {
+            byte[] context = params.getContext().isPresent()
+                    ? params.getContext().get() : null;
+            byte[] initContext = initParam.getContext().isPresent()
+                    ? initParam.getContext().get() : null;
+            boolean preHash = params.isPrehash();
+            boolean initPreHash = initParam.isPrehash();
+            // The signature should not get verified other than same parameter
+            // which is set through the signature instance.
+            if (!(equals(context, initContext) && equals(preHash, initPreHash))) {
+                throw new RuntimeException(String.format("Signature verification"
+                        + " success with different param context(actual:%s, "
+                        + "expected:%s), Prehash(actual:%s, expected:%s)",
+                        Convert.byteArrayToHexString(context),
+                        Convert.byteArrayToHexString(initContext),
+                        preHash, initPreHash));
+            } else {
+                System.out.println("Atleast a case matched");
+            }
+        }
+    }
+
+    private static boolean equals(Object actual, Object expected) {
+
+        if (actual == expected) {
+            return true;
+        }
+        if (actual == null || expected == null) {
+            return false;
+        }
+        boolean equals = actual.equals(expected);
+        if (!equals) {
+            throw new RuntimeException(String.format("Actual: %s, Expected: %s",
+                    actual, expected));
+        }
+        return equals;
+    }
+
+    private static boolean equals(byte[] actual, byte[] expected) {
+
+        if (actual == expected) {
+            return true;
+        }
+        if (actual == null || expected == null) {
+            return false;
+        }
+        boolean equals = Arrays.equals(actual, expected);
+        if (!equals) {
+            throw new RuntimeException(String.format("Actual array: %s, "
+                    + "Expected array:%s", Convert.byteArrayToHexString(actual),
+                    Convert.byteArrayToHexString(expected)));
+        }
+        return equals;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ec/ed/EdDSAReuseTest.java	Tue May 19 02:36:17 2020 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.spec.NamedParameterSpec;
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * @test
+ * @bug 8209632
+ * @summary Test behaviour of Signature instance by re-using it multiple times
+ *          in different way.
+ * @run main EdDSAReuseTest
+ */
+public class EdDSAReuseTest {
+
+    private static final String EDDSA = "EdDSA";
+    private static final String ED25519 = "Ed25519";
+    private static final String ED448 = "Ed448";
+    private static final String PROVIDER = "SunEC";
+    private static final String MSG = "TEST";
+    private static final int REUSE = 20;
+    private static final int ONCE = 1;
+    private static final int TENTH = 10;
+    private static final int FIFTH = 5;
+
+    public static void main(String[] args) throws Exception {
+
+        for (boolean initKey : new boolean[]{true, false}) {
+            // Sign and Verify with data update once
+            test(PROVIDER, EDDSA, null, initKey, ONCE, ONCE);
+            test(PROVIDER, ED25519, ED25519, initKey, ONCE, ONCE);
+            test(PROVIDER, ED448, ED448, initKey, ONCE, ONCE);
+
+            // Sign and Verify with data update 10 times
+            test(PROVIDER, EDDSA, null, initKey, TENTH, TENTH);
+            test(PROVIDER, ED25519, ED25519, initKey, TENTH, TENTH);
+            test(PROVIDER, ED448, ED448, initKey, TENTH, TENTH);
+
+            // Sign and Verify with data update unmatched number of times
+            test(PROVIDER, EDDSA, null, initKey, TENTH, FIFTH);
+            test(PROVIDER, ED25519, ED25519, initKey, TENTH, FIFTH);
+            test(PROVIDER, ED448, ED448, initKey, TENTH, FIFTH);
+        }
+    }
+
+    private static void test(String provider, String name, Object param,
+            boolean initKey, int signUpdate, int verifyUpdate)
+            throws Exception {
+
+        System.out.printf("Case for signature name: %s, param: %s,"
+                + " initialize signature instance before each operation: %s%n",
+                name, param, initKey);
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(name, provider);
+        if (param != null) {
+            kpg.initialize(new NamedParameterSpec((String) param));
+        }
+        KeyPair kp = kpg.generateKeyPair();
+        Signature sig = Signature.getInstance(name, provider);
+        testAPI(sig, kp, initKey, signUpdate, verifyUpdate);
+        System.out.println("Passed.");
+    }
+
+    private static void testAPI(Signature sig, KeyPair kp, boolean initKey,
+            int signUpdate, int verifyUpdate) throws Exception {
+
+        sig.initSign(kp.getPrivate());
+        List<byte[]> signatures = new ArrayList<>();
+        // Re-use the signature instance 20 times
+        for (int i = 0; i < REUSE; i++) {
+            signatures.add(sign(sig, kp.getPrivate(), MSG, initKey, signUpdate));
+        }
+        System.out.printf("Generated signatures %s times%n", signatures.size());
+        sig.initVerify(kp.getPublic());
+        for (byte[] sign : signatures) {
+            // Verification will pass when message update matches with
+            // the same used for sign
+            if (verify(sig, kp.getPublic(), MSG, sign, initKey, verifyUpdate)
+                    != (signUpdate == verifyUpdate)) {
+                throw new RuntimeException(
+                        "Verification succed with unmatched message");
+            }
+        }
+        System.out.printf("Verified signatures %s times%n", signatures.size());
+    }
+
+    private static byte[] sign(Signature sig, PrivateKey priKey, String msg,
+            boolean initKey, int signUpdate) throws Exception {
+        if (initKey) {
+            sig.initSign(priKey);
+        }
+        for (int update = 0; update < signUpdate; update++) {
+            sig.update(msg.getBytes());
+        }
+        return sig.sign();
+    }
+
+    private static boolean verify(Signature sig, PublicKey pubKey, String msg,
+            byte[] sign, boolean initKey, int verifyUpdate) throws Exception {
+        if (initKey) {
+            sig.initVerify(pubKey);
+        }
+        for (int update = 0; update < verifyUpdate; update++) {
+            sig.update(msg.getBytes());
+        }
+        return sig.verify(sign);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ec/ed/EdDSATest.java	Tue May 19 02:36:17 2020 -0700
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import static javax.crypto.Cipher.PRIVATE_KEY;
+import static javax.crypto.Cipher.PUBLIC_KEY;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.interfaces.EdECPrivateKey;
+import java.security.interfaces.EdECPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.security.spec.EdECPrivateKeySpec;
+import java.security.spec.EdECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.NamedParameterSpec;
+import java.security.spec.EdDSAParameterSpec;
+import java.util.Arrays;
+import jdk.test.lib.Convert;
+
+/*
+ * @test
+ * @bug 8209632
+ * @summary Test Signature with variation of serialized EDDSA Keys.
+ * @library /test/lib
+ * @build jdk.test.lib.Convert
+ * @run main EdDSATest
+ */
+public class EdDSATest {
+
+    private static final String EDDSA = "EdDSA";
+    private static final String ED25519 = "Ed25519";
+    private static final String ED448 = "Ed448";
+    private static final String OIDN25519 = "1.3.101.112";
+    private static final String OID25519 = "OID.1.3.101.112";
+    private static final String OIDN448 = "1.3.101.113";
+    private static final String OID448 = "OID.1.3.101.113";
+    private static final String PROVIDER = "SunEC";
+    private static final byte[] MSG = "TEST".getBytes();
+    private static final SecureRandom S_RND = new SecureRandom(new byte[]{0x1});
+
+    public static void main(String[] args) throws Exception {
+
+        for (boolean random : new boolean[]{true, false}) {
+
+            // Default Parameter
+            test(PROVIDER, EDDSA, null, random);
+            test(PROVIDER, ED25519, null, random);
+            test(PROVIDER, ED448, null, random);
+
+            // With named parameter
+            test(PROVIDER, EDDSA, ED25519, random);
+            test(PROVIDER, ED25519, ED25519, random);
+            test(PROVIDER, OIDN25519, ED25519, random);
+            test(PROVIDER, OID25519, ED25519, random);
+            test(PROVIDER, ED448, ED448, random);
+            test(PROVIDER, OIDN448, ED448, random);
+            test(PROVIDER, OID448, ED448, random);
+
+            // With size parameter
+            test(PROVIDER, EDDSA, 255, random);
+            test(PROVIDER, ED25519, 255, random);
+            test(PROVIDER, OIDN25519, 255, random);
+            test(PROVIDER, OID25519, 255, random);
+            test(PROVIDER, ED448, 448, random);
+            test(PROVIDER, OIDN448, 448, random);
+            test(PROVIDER, OID448, 448, random);
+        }
+    }
+
+    // Test signature using a KeyPair and the corresponding transformed one.
+    private static void test(String provider, String name, Object param,
+            boolean random) throws Exception {
+
+        System.out.printf("Case Algo:%s, Param:%s, Intitiate with random:%s%n",
+                name, param, random);
+        KeyPair origkp = genKeyPair(provider, name, param, random);
+        testSignature(provider, name, origkp, origkp);
+        NamedParameterSpec namedSpec = namedParamSpec(name);
+        // Test all possible transformed private/public keys
+        for (Key priKey : manipulateKey(provider, name, PRIVATE_KEY,
+                origkp.getPrivate(), namedSpec)) {
+            for (Key pubKey : manipulateKey(provider, name, PUBLIC_KEY,
+                    origkp.getPublic(), namedSpec)) {
+                EdECPrivateKey pri = (EdECPrivateKey) priKey;
+                EdECPublicKey pub = (EdECPublicKey) pubKey;
+                // Test the keys are serializable.
+                testSerialize(origkp, new KeyPair(pub, pri));
+                // Test signature
+                testSignature(provider, name, origkp, new KeyPair(pub, pri));
+            }
+        }
+        System.out.println("Passed.");
+    }
+
+    private static KeyPair genKeyPair(String provider, String name,
+            Object param, boolean random) throws Exception {
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(name, provider);
+        if (random) {
+            if (param instanceof Integer) {
+                kpg.initialize((Integer) param, S_RND);
+            } else if (param instanceof String) {
+                kpg.initialize(new NamedParameterSpec((String) param), S_RND);
+            }
+        } else {
+            if (param instanceof Integer) {
+                kpg.initialize((Integer) param);
+            } else if (param instanceof String) {
+                kpg.initialize(new NamedParameterSpec((String) param));
+            }
+        }
+        equals(kpg.getProvider().getName(), provider);
+        equals(kpg.getAlgorithm(), name);
+        return kpg.generateKeyPair();
+    }
+
+    private static NamedParameterSpec namedParamSpec(String algo) {
+        NamedParameterSpec namedSpec = switch (algo) {
+            case EDDSA
+                , OIDN25519, OID25519 -> new NamedParameterSpec(ED25519);
+            case OIDN448
+                , OID448 -> new NamedParameterSpec(ED448);
+            default->
+                new NamedParameterSpec(algo);
+        };
+            return namedSpec;
+    }
+
+    private static Key[] manipulateKey(String provider, String name, int type,
+            Key key, NamedParameterSpec namedSpec)
+            throws NoSuchAlgorithmException, InvalidKeySpecException,
+            NoSuchProviderException, InvalidKeyException {
+
+        KeyFactory kf = KeyFactory.getInstance(name, provider);
+        switch (type) {
+            case PUBLIC_KEY:
+                return new Key[]{
+                    kf.generatePublic(new X509EncodedKeySpec(key.getEncoded())),
+                    kf.generatePublic(kf.getKeySpec(
+                    key, EdECPublicKeySpec.class)),
+                    kf.generatePublic(new EdECPublicKeySpec(namedSpec,
+                    ((EdECPublicKey) key).getPoint())),
+                    kf.translateKey(key)
+                };
+            case PRIVATE_KEY:
+                return new Key[]{
+                    kf.generatePrivate(new PKCS8EncodedKeySpec(key.getEncoded())),
+                    kf.generatePrivate(
+                    kf.getKeySpec(key, EdECPrivateKeySpec.class)),
+                    kf.generatePrivate(new EdECPrivateKeySpec(namedSpec,
+                    ((EdECPrivateKey) key).getBytes().get())),
+                    kf.translateKey(key)
+                };
+        }
+        throw new RuntimeException("We shouldn't reach here");
+    }
+
+    /**
+     * Test Signature with a set of parameter combination.
+     */
+    private static void testSignature(String provider, String name,
+            KeyPair origkp, KeyPair kp) throws Exception {
+
+        signAndVerify(provider, name, origkp, kp, null);
+        // Test Case with Pre-Hash enabled and disabled.
+        for (boolean preHash : new boolean[]{true, false}) {
+            signAndVerify(provider, name, origkp, kp,
+                    new EdDSAParameterSpec(preHash));
+            // Test Case with Context combined.
+            for (byte[] context : new byte[][]{
+                {}, "a".getBytes(), new byte[255]}) {
+                signAndVerify(provider, name, origkp, kp,
+                        new EdDSAParameterSpec(preHash, context));
+            }
+        }
+    }
+
+    private static void signAndVerify(String provider, String name,
+            KeyPair origkp, KeyPair kp, EdDSAParameterSpec params)
+            throws Exception {
+
+        Signature sig = Signature.getInstance(name, provider);
+        if (params != null) {
+            sig.setParameter(params);
+        }
+        sig.initSign(origkp.getPrivate());
+        sig.update(MSG);
+        byte[] origSign = sig.sign();
+
+        sig.update(MSG);
+        byte[] computedSig = sig.sign();
+        equals(origSign, computedSig);
+        // EdDSA signatures size (64 and 114 bytes) for Ed25519 and Ed448.
+        int expectedSigSize = edSignatureSize(name);
+        equals(origSign.length, expectedSigSize);
+        sig.initSign(kp.getPrivate());
+        sig.update(MSG);
+        equals(computedSig, sig.sign());
+        // Use same signature instance to verify with transformed PublicKey.
+        sig.initVerify(kp.getPublic());
+        sig.update(MSG);
+        if (!sig.verify(origSign)) {
+            throw new RuntimeException(String.format("Signature did not verify"
+                    + " for name:%s, prehash:%s, context:%s", name,
+                    (params == null) ? null : params.isPrehash(),
+                    (params == null) ? null : params.getContext().get()));
+        }
+
+        // Create a new signature to re-verify.
+        sig = Signature.getInstance(name, provider);
+        if (params != null) {
+            sig.setParameter(params);
+        }
+        // Verify the signature with transformed PublicKey.
+        sig.initVerify(kp.getPublic());
+        sig.update(MSG);
+        if (!sig.verify(origSign)) {
+            throw new RuntimeException(String.format("Signature did not verify"
+                    + " for name:%s, prehash:%s, context:%s",
+                    name, (params == null) ? null : params.isPrehash(),
+                    (params == null) ? null : params.getContext().get()));
+        }
+        equals(sig.getAlgorithm(), name);
+        equals(sig.getProvider().getName(), provider);
+    }
+
+    private static int edSignatureSize(String algo) {
+        int size = switch (algo) {
+            case EDDSA
+                , ED25519, OIDN25519, OID25519 -> 64;
+            case ED448
+                , OIDN448, OID448 -> 114;
+            default->
+                -1;
+        };
+            return size;
+    }
+
+    /**
+     * Compare original KeyPair with transformed ones.
+     */
+    private static void testKeyEquals(KeyPair origkp, PublicKey pubKey,
+            PrivateKey priKey) {
+
+        if (!origkp.getPrivate().equals(priKey)
+                && !Arrays.equals(origkp.getPrivate().getEncoded(),
+                        priKey.getEncoded())
+                && origkp.getPrivate().hashCode() != priKey.hashCode()) {
+            throw new RuntimeException(
+                    "PrivateKey is not equal with transformed one");
+        }
+        if (!origkp.getPublic().equals(pubKey)
+                && !Arrays.equals(origkp.getPublic().getEncoded(),
+                        pubKey.getEncoded())
+                && origkp.getPublic().hashCode() != pubKey.hashCode()) {
+            throw new RuntimeException(
+                    "PublicKey is not equal with transformed one");
+        }
+    }
+
+    /**
+     * Test serialization of KeyPair and Keys.
+     */
+    private static void testSerialize(KeyPair origkp, KeyPair kp)
+            throws Exception {
+
+        testKeyEquals(origkp, kp.getPublic(), kp.getPrivate());
+        PrivateKey priv = deserializedCopy(kp.getPrivate(), PrivateKey.class);
+        PublicKey pub = deserializedCopy(kp.getPublic(), PublicKey.class);
+        testKeyEquals(origkp, pub, priv);
+        // Verify Serialized KeyPair instance.
+        KeyPair copy = deserializedCopy(kp, KeyPair.class);
+        testKeyEquals(origkp, copy.getPublic(), copy.getPrivate());
+    }
+
+    private static <T extends Object> T deserializedCopy(T origkp, Class<T> type)
+            throws IOException, ClassNotFoundException {
+        return deserialize(serialize(origkp), type);
+    }
+
+    /**
+     * Deserialize the Key object.
+     */
+    private static <T extends Object> T deserialize(byte[] serialized,
+            Class<T> type) throws IOException, ClassNotFoundException {
+
+        T key = null;
+        try (ByteArrayInputStream bis = new ByteArrayInputStream(serialized);
+                ObjectInputStream ois = new ObjectInputStream(bis)) {
+            key = (T) ois.readObject();
+        }
+        return key;
+    }
+
+    /**
+     * Serialize the given Key object.
+     */
+    private static <T extends Object> byte[] serialize(T key)
+            throws IOException {
+
+        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+            oos.writeObject(key);
+            return bos.toByteArray();
+        }
+    }
+
+    private static void equals(Object actual, Object expected) {
+        if (!actual.equals(expected)) {
+            throw new RuntimeException(String.format("Actual: %s, Expected: %s",
+                    actual, expected));
+        }
+    }
+
+    private static void equals(byte[] actual, byte[] expected) {
+        if (!Arrays.equals(actual, expected)) {
+            throw new RuntimeException(String.format("Actual array: %s, "
+                    + "Expected array:%s", Convert.byteArrayToHexString(actual),
+                    Convert.byteArrayToHexString(expected)));
+        }
+    }
+}