Reputation: 3227
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
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