KunLun
KunLun

Reputation: 3227

String to PrivateKey Ed25519

I have a private key as a String and I want to convert it to PrivateKey

String privateKey = "Y2E3YjYwYzRjMDRjMjk1ZDQ5ZTQzM2RlMTdjZjVkNGE0NGFjYzJmM2IzOWExNWZhMjViNGE4ZWJiZDBiMDVkYTIwNGU4MWE3ZWZmMTQ0NGE2ZmM2NjExNzRmNTY4M2I0YmYyMTk5YTkyY2UzOWRkZjdmMzhkNTFjYTNmM2Q3ZDU";

byte[] pkcs8EncodedBytes = Base64.getDecoder().decode(privateKey);

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);

PrivateKey pkey = KeyFactory.getInstance("Ed25519") //NoSuchAlgorithmException
                            .generatePrivate(keySpec);

But I get this error:

java.security.NoSuchAlgorithmException: Ed25519 KeyFactory not available

at KeyFactory.getInstance("Ed25519")

I'm using Java-10

Upvotes: 3

Views: 3048

Answers (1)

Topaco
Topaco

Reputation: 49400

The posted key is double encoded, first hex, then Base64. Note that the double encoding is not necessary. If the key is Base64 and hex decoded, the result is a 64 bytes key.

From this 64 bytes key the first 32 bytes are the secret key and the following 32 bytes are the public key. More details about this format can be found here.

Import, signing and verification with BouncyCastle are possible with Ed25519PrivateKeyParameters, Ed25519PublicKeyParameters and Ed25519Signer classes:

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.bouncycastle.crypto.Signer;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
import org.bouncycastle.crypto.signers.Ed25519Signer;
import org.bouncycastle.util.encoders.Hex;

// Base64, hex decode
String keyHexBase64 ="Y2E3YjYwYzRjMDRjMjk1ZDQ5ZTQzM2RlMTdjZjVkNGE0NGFjYzJmM2IzOWExNWZhMjViNGE4ZWJiZDBiMDVkYTIwNGU4MWE3ZWZmMTQ0NGE2ZmM2NjExNzRmNTY4M2I0YmYyMTk5YTkyY2UzOWRkZjdmMzhkNTFjYTNmM2Q3ZDU";
byte[] key = Hex.decode(new String(Base64.getDecoder().decode(keyHexBase64), StandardCharsets.UTF_8));

// Separate secret and public key
ByteBuffer keyBuffer = ByteBuffer.wrap(key);
byte[] secretKey = new byte[32];
keyBuffer.get(secretKey);
byte[] publicKey = new byte[keyBuffer.remaining()];
keyBuffer.get(publicKey);

// Signing
byte[] message = "The quick brown fox jumps over the lazy dog".getBytes(StandardCharsets.UTF_8);
Ed25519PrivateKeyParameters secretKeyParameters = new Ed25519PrivateKeyParameters(secretKey, 0);
Signer signer = new Ed25519Signer();
signer.init(true, secretKeyParameters);
signer.update(message, 0, message.length);
byte[] signature = signer.generateSignature();
System.out.println("Signature (hex): " + Hex.toHexString(signature));

// Verification
Ed25519PublicKeyParameters publicKeyParameters = new Ed25519PublicKeyParameters(publicKey, 0);
Signer verifier = new Ed25519Signer();
verifier.init(false, publicKeyParameters);
verifier.update(message, 0, message.length);
boolean verified = verifier.verifySignature(signature); // Signature (hex): 2aa31bb14799a00ac1129bdd6773a8481f0fd7e829d59f6fccc81021bf21e397dc5d17362d342615a5500598542586cad8891f984bdb90ec0c80b48eb638df07
System.out.println("Verification: " + verified); // Verification: true

Regarding BouncyCastle, bcprov-jdk15on is required, which can be loaded from the Maven repository or from the BouncyCastle website.

Upvotes: 2

Related Questions