How to regenerate private key using EdDSA/Ed448 signature algorithm?

Here is how I generated the key pair:

var keyPairGenerator = KeyPairGenerator.getInstance("Ed448");
keyPairGenerator.initialize(448, SecureRandom.getInstanceStrong());
var keyPair = keyPairGenerator.generateKeyPair();
var privateKey = keyPair.getPrivate();
var publicKey = keyPair.getPublic();
byte[] privateKeyBytes = privateKey.getEncoded();
byte[] publicKeyBytes = publicKey.getEncoded();

However, when I tried to regenerate the keys again, I got an exception:

var keyFactory = KeyFactory.getInstance("EdDSA");
var edECPoint = byteArrayToEdPoint(publicKeyBytes);
var edECPublicKeySpec = new EdECPublicKeySpec(new NamedParameterSpec("Ed448"), edECPoint);
var publicKey = keyFactory.generatePublic(edECPublicKeySpec);
var edECPrivateKeySpec = new EdECPrivateKeySpec(new NamedParameterSpec("Ed448"), privateKeyBytes);
var privateKey = keyFactory.generatePrivate(edECPrivateKeySpec); // generatePrivate() throws exception

The exception stacktrace:

Exception in thread "main" key length is 73, key length must be 57
    at java.base/
    at io.fouad.Main.main(
Caused by: key length is 73, key length must be 57
    ... 2 more

and here is some utilities I copied from OpenJDK repo:

private static EdECPoint byteArrayToEdPoint(byte[] arr)
    byte msb = arr[arr.length - 1];
    boolean xOdd = (msb & 0x80) != 0;
    arr[arr.length - 1] &= (byte) 0x7F;
    BigInteger y = new BigInteger(1, arr);
    return new EdECPoint(xOdd, y);

private static void reverse(byte [] arr)
    int i = 0;
    int j = arr.length - 1;
    while(i < j)
        swap(arr, i, j);

private static void swap(byte[] arr, int i, int j)
    byte tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;


  • Since privateKey.getEncoded(the instance will be of EdDSAPrivateKeyImpl type) will return a key in PKCS8 format, you should use PKCS8EncodedKeySpec :

    var keyFactory = KeyFactory.getInstance("EdDSA");
    var pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
    var privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

    Otherwise you would have to unwrap the the sequence yourself and get PrivateKey (this is OctetString) as described in RFC5958-section2. Then you could use EdECPrivateKeySpec.