如何使用java从私钥派生出eddsa(ed25519)公钥

a9wyjsp7  于 2021-07-12  发布在  Java
关注(0)|答案(1)|浏览(865)

我正在调查https://github.com/str4d/ed25519-java 库以及其他一些库,如bouncycastle,但到目前为止在生成公钥方面还没有成功。我对生成密钥对不感兴趣,因为我已经有了私钥,只对生成相应的公钥感兴趣。

c2e8gylq

c2e8gylq1#

使用bouncy castle(bc)作为加密提供程序库总是一个不错的选择,而且它们具有从现有私钥派生公钥的“内置”支持。请记住,bc不使用私钥或公钥,而是使用ed25519privatekeyparameters和ed25519publickeyparameters,但正如您所见,从编码密钥中获取它们非常容易。
完整的程序稍微长一点,以证明重建公钥能够验证由其相应的私钥生成的签名。因此,程序的主要部分是生成和验证一个ed25519签名。
这两行是在做你想做的事:

Ed25519PrivateKeyParameters privateKeyRebuild = new Ed25519PrivateKeyParameters(privateKeyEncoded, 0);
Ed25519PublicKeyParameters publicKeyRebuild = privateKeyRebuild.generatePublicKey();

以下行正在使用重建公钥成功验证签名。
输出:

ED25519 signature with BC and deriving public key from private key
signature Length  :64 Data:218c6dd5053ee22e94325981cdeb81d623b80715b21495d22ef9d8dbf0c4a097699747bafedbd2fd2bcdfdededb2664ea5b732e2242b7cb92ddd6e51acbed30e
signature correct :true
Rebuild the keys and verify the signature with rebuild public key
signature correct :true

安全警告:该代码没有任何异常处理,仅用于教育目的。
代码:

import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.Signer;
import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator;
import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
import org.bouncycastle.crypto.signers.Ed25519Signer;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.Security;

public class Ed25519SignatureWithPublicKeyDeriving {
    public static void main(String[] args) throws CryptoException {
        System.out.println("ED25519 signature with BC and deriving public key from private key");
        Security.addProvider(new BouncyCastleProvider());
        // generate ed25519 keys
        SecureRandom RANDOM = new SecureRandom();
        Ed25519KeyPairGenerator keyPairGenerator = new Ed25519KeyPairGenerator();
        keyPairGenerator.init(new Ed25519KeyGenerationParameters(RANDOM));
        AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();
        Ed25519PrivateKeyParameters privateKey = (Ed25519PrivateKeyParameters) asymmetricCipherKeyPair.getPrivate();
        Ed25519PublicKeyParameters publicKey = (Ed25519PublicKeyParameters) asymmetricCipherKeyPair.getPublic();
        // the message
        byte[] message = "Message to sign".getBytes(StandardCharsets.UTF_8);
        // create the signature
        Signer signer = new Ed25519Signer();
        signer.init(true, privateKey);
        signer.update(message, 0, message.length);
        byte[] signature = signer.generateSignature();
        // verify the signature
        Signer verifier = new Ed25519Signer();
        verifier.init(false, publicKey);
        verifier.update(message, 0, message.length);
        boolean shouldVerify = verifier.verifySignature(signature);
        // output
        System.out.println("signature Length  :" + signature.length + " Data:" + bytesToHex(signature));
        System.out.println("signature correct :" + shouldVerify);

        // derive pub key from private key, here in encoded
        byte[] privateKeyEncoded = privateKey.getEncoded();
        // rebuild the keys
        System.out.println("Rebuild the keys and verify the signature with rebuild public key");
        Ed25519PrivateKeyParameters privateKeyRebuild = new Ed25519PrivateKeyParameters(privateKeyEncoded, 0);
        Ed25519PublicKeyParameters publicKeyRebuild = privateKeyRebuild.generatePublicKey();
        // verify the signature
        Signer verifierDerived = new Ed25519Signer();
        verifierDerived.init(false, publicKeyRebuild);
        verifierDerived.update(message, 0, message.length);
        boolean shouldVerifyDerived = verifierDerived.verifySignature(signature);
        System.out.println("signature correct :" + shouldVerifyDerived);
    }
    private static String bytesToHex(byte[] bytes) {
        StringBuffer result = new StringBuffer();
        for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
        return result.toString();
    }
}

相关问题