将字符串转换为Ed25519私钥

3

我有一个私钥字符串,想要将其转换为PrivateKey

String privateKey = "Y2E3YjYwYzRjMDRjMjk1ZDQ5ZTQzM2RlMTdjZjVkNGE0NGFjYzJmM2IzOWExNWZhMjViNGE4ZWJiZDBiMDVkYTIwNGU4MWE3ZWZmMTQ0NGE2ZmM2NjExNzRmNTY4M2I0YmYyMTk5YTkyY2UzOWRkZjdmMzhkNTFjYTNmM2Q3ZDU";

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

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);

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

但是我遇到了这个错误:

java.security.NoSuchAlgorithmException: Ed25519 KeyFactory不可用

KeyFactory.getInstance("Ed25519")

我正在使用Java-10


2
Java 15已支持Ed25519。对于早期的Java版本,BouncyCastle是一个选择。然而,您的密钥Base64解码后只有4个字节,这对于Ed25519密钥来说太小了。 - Topaco
1
在Java10中,您只能使用这些KeyFactory算法 https://docs.oracle.com/javase/10/docs/specs/security/standard-names.html#keyfactory-algorithms - dcolazin
@Topaco,关于密钥,我知道,我只是随便放了一些东西,以免在这里放真正的值。关于 BouncyCastle,我尝试在 mvnrepository 上找到它,但我不知道该选择哪个版本。你能帮我吗? - KunLun
您不需要(也不应该)发布一个“真实”的密钥,但您应该指定密钥格式(或者提供一个“测试”密钥)。假设您想要导入“raw”密钥,可以使用BouncyCastle(即提供程序jar,bcprov),请参阅这里获取代码示例。或者,您可以使用前缀0x302e020100300506032b657004220420进行“raw到PKCS#8”转换,然后使用PKCS8EncodedKeySpec进行标准导入(此前缀仅适用于原始的私有Ed25519密钥)。 - Topaco
@Topaco,我放了一个测试密钥。由于原始的Java 10不起作用,我的意图是使用Ed25519算法使用该私钥对某些数据进行签名。 - KunLun
1个回答

2
发布的密钥是双重编码的,首先是十六进制,然后是Base64。请注意,双重编码不是必需的。如果密钥经过Base64和十六进制解码,则结果是一个64字节的密钥。
从这个64字节的密钥中,前32个字节是秘密密钥,接下来的32个字节是公共密钥。有关此格式的更多详细信息,请单击此处
可以使用Ed25519PrivateKeyParametersEd25519PublicKeyParametersEd25519Signer类导入、签名和验证BouncyCastle。
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

关于BouncyCastle,需要使用bcprov-jdk15on,可以从Maven仓库BouncyCastle网站加载。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接