Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8348036

Ed448 and Ed25519 subject public keys in X.509 certificates materialize as EdDSA

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      Java 15 onwards, last tested OpenJDK Runtime Environment Temurin-23+37 (build 23+37) on Ubuntu 24.10

      A DESCRIPTION OF THE PROBLEM :
      When parsing an X.509 certificate that contains either an Ed448 or Ed25519 key as the subject public key, a Certificate object is returned. If this certificate object is queried for the subject public key, a key is returned where the getAlgorithm method reports EdDSA instead of the actual algorithm. Both openSSL and BouncyCastle (used as a provider) report the key as Ed448/Ed25519.

      I consider myself not as a security expert, but I know that EdDSA is related to Ed448 and Ed25519 (i.e. the "family" name of the algorithms). However, the algorithms are distinguished on the ASN.1 level, having different OIDs (as documented in RFC 8410). So I am of the opinion that the algorithms should be better reported correctly.

      Maybe some background how I discovered the issue:

      I am developing a library which has to create and store public-private keys of various algorithms. For the storage, I use the common practice of storing the key pair in either a Java or PKCS#12 keystore in form of a PrivateKeyEntry. I use BouncyCastle to create the key pairs and to create the respective dummy certificates. Until now, the library ran under Java 8, with BouncyCastle providing the implementations of the Ed448 and Ed25519 algorithms. I don't know how BouncyCastle workds under the hood, but it seems to use the CertificateFactory infrastructure to convert the ASN.1 assembled certificate to a Java instance. When I tried to create a PrivateKeyEntry, I got an IllegalArgumentException ("private key algorithm does not match algorithm of public key in end entity certificate"). A quick look into the code revealed that there is a comparison between the algorithms of the public and private keys, namely EeDSA vs. Ed448/Ed25519. I tracked down that the problems started with Java 15, where the own support for these algorithms have been introduced.



      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the provided test case.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Ed448 and Ed25519 to be printed.
      ACTUAL -
      EdDSA printed for both certificates.


      ---------- BEGIN SOURCE ----------
      import java.security.cert.Certificate;
      import java.security.cert.CertificateFactory;
      import java.io.ByteArrayInputStream;


      public class Test
      {

        public static void main (String[] args)
          throws Exception
        {
          String[] pemCerts =
            {
              "-----BEGIN CERTIFICATE-----\n" +
              "MIIBOTCBuqADAgECAgEBMAUGAytlcTAQMQ4wDAYDVQQDDAVrZXktMjAeFw0xNjAx\n" +
              "MDEwMDAwMDBaFw0zNjAxMDEwMDAwMDBaMBAxDjAMBgNVBAMMBWtleS0yMEMwBQYD\n" +
              "K2VxAzoA88MKsU4KgYUdAd/o/mr3PM6QN2ltTxEgXc1LFro9mTxSuhbx/zVPrj+t\n" +
              "/o7ZDFDnb0Z74NSNt+0AoyAwHjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIH\n" +
              "gDAFBgMrZXEDcwCk9nz2zid0r0TYk+pcUdCZAeDcWMVELJEx45mFYTw8GywNj7tM\n" +
              "11zMpj7IquJYlLEO7l5WGxVYQgD7Mk2lPHNd75Vwh2S7qphqqql/5rA812rUVBAN\n" +
              "FAmq2j9oXTym0rYdR3AQL1Xec+mVRtm5cLAWMAA=\n" +
              "-----END CERTIFICATE-----\n",

              "-----BEGIN CERTIFICATE-----\n" +
              "MIHuMIGhoAMCAQICAQEwBQYDK2VwMBAxDjAMBgNVBAMMBWtleS0yMB4XDTE2MDEw\n" +
              "MTAwMDAwMFoXDTM2MDEwMTAwMDAwMFowEDEOMAwGA1UEAwwFa2V5LTIwKjAFBgMr\n" +
              "ZXADIQAT8WjklO648Yn3onR7Y5lHKMZRNJYf394BZDwYJpEvQ6MgMB4wDAYDVR0T\n" +
              "AQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwBQYDK2VwA0EAaVKxZvtZUVahxWC7qmRd\n" +
              "twxuaid9nIO5bMi9cYwoyQNkDVUCVKuQoDcUlmsieIleAEOWOeQRaN9k5T6SPpT2\n" +
              "Ag==\n" +
              "-----END CERTIFICATE-----\n"
            };

          for (String pemCert: pemCerts)
          {
            System.out.print (pemCert);

            CertificateFactory cf = CertificateFactory.getInstance ("X.509");

            Certificate cert = cf.generateCertificate (
              new ByteArrayInputStream (pemCert.getBytes ("ASCII")));

            System.out.println ("public key algorithm: " +
              cert.getPublicKey ().getAlgorithm ());
          }
        }
      }


      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Use of the BouncyCastle implementation of the CertificateFactory

      FREQUENCY : always


            kthirupattur Koushik Muthukrishnan Thirupattur
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: