![](/img/trans.png)
[英]java.security.NoSuchAlgorithmException: Algorithm x25519 not available
[英]How to generate PublicKey for PrivateKey in X25519?
我目前正在使用基于 X25519 密钥的加密。
我的问题是,基本上,如何从现有的 X25519 PrivateKey
派生PublicKey
?
我在XDHKeyPairGenerator
中找到了代码:
BigInteger publicKey = ops.computePublic(privateKey.clone());
但是这个 package 是特定于平台的,因此无法访问。 而且我找不到通过可公开访问的接口执行此操作的方法。
您必须将私钥(只是一个大数字)乘以25519 曲线生成点。
下面是 python 中的一些代码来说明:
from tinyec import registry
import secrets
curve = registry.get_curve('curve25519')
def compress_point(point):
return hex(point.x) + hex(point.y % 2)[2:]
privKey = secrets.randbelow(curve.field.n)
pubKey = privKey * curve.g //the key step for you...
print("private key:", hex(privKey))
print("public key:", compress_point(pubKey))
如果您让我知道 Java 库,我会尽力提供进一步帮助。
到目前为止,我只发现了一种通过 JDK 提供的接口来实现它的方法(不使用任何额外的库,如 Bouncy Castle 或 Google Tink):
public class StaticSecureRandom extends SecureRandom {
private final byte[] privateKey;
public StaticSecureRandom(byte[] privateKey) {
this.privateKey = privateKey.clone();
}
@Override
public void nextBytes(byte[] bytes) {
System.arraycopy(privateKey, 0, bytes, 0, privateKey.length);
}
}
public PublicKey generatePublicKeyFromPrivate(PrivateKey privateKey) throws GeneralSecurityException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(X25519);
keyPairGenerator.initialize(new NamedParameterSpec(X25519), new StaticSecureRandom(getScalar(privateKey)));
return keyPairGenerator.generateKeyPair().getPublic();
}
这不是一个非常优雅的解决方案,但它可以在没有任何第三方库的情况下工作,而且我找不到任何其他方式。
BouncyCastle 有 Ed25519KeyPairGenerator、X25519KeyPairGenerator、PrivateKeyInfoFactory 和 SubjectPublicKeyInfoFactory 可以协助制作密钥。 这是 C# 中的一个示例。 用 X25519KeyPairGenerator 替换 ECKeyPairGenerator。 此示例使用标准键和 NIST 曲线,因为我无法让 Curve25519 使用 X25519 生成的键,因为当前实现不支持 oid。
public static async Task Bouncy()
{
var originalSecret = "X25519 example";
var message = Encoding.UTF8.GetBytes(originalSecret);
// Generate signing keys
var gen = new Ed25519KeyPairGenerator();
gen.Init(new Ed25519KeyGenerationParameters(new SecureRandom()));
var kp = gen.GenerateKeyPair();
// Sign data with private key
var signer = new Ed25519Signer();
signer.Init(true, kp.Private);
signer.BlockUpdate(message, 0, message.Length);
var sig = signer.GenerateSignature();
// Verify signature with public key
var verifier = new Ed25519Signer();
verifier.Init(false, kp.Public);
verifier.BlockUpdate(message, 0, message.Length);
var sigresult = verifier.VerifySignature(sig);
// Generate encryption keys
var genX = new ECKeyPairGenerator();
genX.Init(new KeyGenerationParameters(new SecureRandom(), 521));
var p1 = genX.GenerateKeyPair();
var p1_private = ECPrivateKeyStructure.GetInstance(PrivateKeyInfoFactory.CreatePrivateKeyInfo(p1.Private));
var p1_x25519_priv = new X25519PrivateKeyParameters(p1_private.GetDerEncoded(), 0);
var p2 = genX.GenerateKeyPair();
var p2_public = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(p2.Public);
var p2_x25519_pub = new X25519PublicKeyParameters(p2_public.GetDerEncoded(), 0);
// Generate secret from keys
var secret = new byte[32];
p1_x25519_priv.GenerateSecret(p2_x25519_pub, secret, 0);
// Setup ECIES (Elliptical Curve Integrated Encryption Scheme)
var gcm = new GcmBlockCipher(new AesEngine());
var ies = new IesEngine(new ECDHBasicAgreement(), new Kdf2BytesGenerator(new Sha512Digest()),
new HMac(new Sha512Digest()), new PaddedBufferedBlockCipher(gcm.GetUnderlyingCipher()));
// 256bit MAC, 256 key
var p = new IesWithCipherParameters(secret, new byte[1], 256, 256);
// Encrypt secret
ies.Init(true, p1.Private, p2.Public, p);
var encrypted = ies.ProcessBlock(message, 0, message.Length);
// Decrypt secret
ies.Init(false, p2.Private, p1.Public, p);
var decrypted = ies.ProcessBlock(encrypted, 0, encrypted.Length);
var decrypted_string = Encoding.UTF8.GetString(decrypted);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.