【问题标题】:How derive ed25519 (eddsa) public key from private key using Java如何使用 Java 从私钥派生 ed25519 (eddsa) 公钥
【发布时间】:2020-11-17 00:39:46
【问题描述】:

我正在研究 https://github.com/str4d/ed25519-java 库以及 BouncyCastle 等其他一些库,但到目前为止我还没有成功从私钥生成公钥。我对生成密钥对不感兴趣,因为我已经有一个私钥并且只对生成相应的公钥感兴趣。

【问题讨论】:

    标签: java cryptography ed25519 eddsa


    【解决方案1】:

    使用 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();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-15
      • 2020-04-04
      • 2022-07-26
      • 2020-05-01
      • 1970-01-01
      相关资源
      最近更新 更多